summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/animation/AnimationHandler.java3
-rw-r--r--core/java/android/app/WallpaperManager.java15
-rw-r--r--core/java/android/service/wallpaper/IWallpaperService.aidl2
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java3
-rw-r--r--core/java/android/view/RemoteAnimationTarget.java12
-rw-r--r--core/java/com/android/internal/dynamicanimation/animation/DynamicAnimation.java815
-rw-r--r--core/java/com/android/internal/dynamicanimation/animation/FloatValueHolder.java64
-rw-r--r--core/java/com/android/internal/dynamicanimation/animation/Force.java27
-rw-r--r--core/java/com/android/internal/dynamicanimation/animation/SpringAnimation.java314
-rw-r--r--core/java/com/android/internal/dynamicanimation/animation/SpringForce.java323
-rw-r--r--core/res/res/values/config.xml6
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java71
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TransactionManager.java201
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java15
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TransactionManagerTest.java204
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasks.aidl4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasksListener.aidl8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java13
-rw-r--r--packages/SoundPicker/res/values-am/strings.xml2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt2
-rw-r--r--packages/SystemUI/ktfmt_includes.txt6
-rw-r--r--packages/SystemUI/res-keyguard/values-as/strings.xml10
-rw-r--r--packages/SystemUI/res/layout/chipbar.xml (renamed from packages/SystemUI/res/layout/media_ttt_chip.xml)4
-rw-r--r--packages/SystemUI/res/values-am/strings.xml54
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml36
-rw-r--r--packages/SystemUI/res/values-as/strings.xml44
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml36
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml36
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml36
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml36
-rw-r--r--packages/SystemUI/res/values-da/strings.xml36
-rw-r--r--packages/SystemUI/res/values-de/strings.xml36
-rw-r--r--packages/SystemUI/res/values-es/strings.xml36
-rw-r--r--packages/SystemUI/res/values-et/strings.xml36
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml36
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml36
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml36
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml36
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml36
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml36
-rw-r--r--packages/SystemUI/res/values-in/strings.xml36
-rw-r--r--packages/SystemUI/res/values-is/strings.xml36
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml36
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml36
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml36
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml36
-rw-r--r--packages/SystemUI/res/values-ml/strings.xml36
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml36
-rw-r--r--packages/SystemUI/res/values-my/strings.xml36
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml36
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml36
-rw-r--r--packages/SystemUI/res/values-or/strings.xml36
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml36
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml36
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml36
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml36
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml36
-rw-r--r--packages/SystemUI/res/values-si/strings.xml36
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml36
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml36
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml36
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml36
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml36
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml36
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml36
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml10
-rw-r--r--packages/SystemUI/res/values/bools.xml7
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/ClockEventController.kt98
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt31
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt169
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodLockscreenTransitionInteractor.kt77
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt49
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt37
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenBouncerTransitionInteractor.kt98
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt42
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt34
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/shared/model/StatusBarState.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionInfo.kt35
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionState.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionStep.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt116
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/README.md2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt113
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt62
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/domain/model/ShadeModel.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt (renamed from packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt)93
-rw-r--r--packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarRootView.kt (renamed from packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipRootView.kt)6
-rw-r--r--packages/SystemUI/tests/Android.bp50
-rw-r--r--packages/SystemUI/tests/Android.mk93
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt155
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt259
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt63
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt459
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt (renamed from packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt)448
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/FakeChipbarCoordinator.kt64
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt4
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java24
-rw-r--r--services/core/java/com/android/server/display/BrightnessTracker.java10
-rw-r--r--services/core/java/com/android/server/display/DisplayDeviceConfig.java42
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java10
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java9
-rw-r--r--services/core/java/com/android/server/display/PersistentDataStore.java35
-rw-r--r--services/core/java/com/android/server/power/AmbientDisplaySuppressionController.java25
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java45
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartController.java6
-rw-r--r--services/core/java/com/android/server/wm/SafeActivityOptions.java17
-rw-r--r--services/core/xsd/display-device-config/display-device-config.xsd1
-rw-r--r--services/core/xsd/display-device-config/schema/current.txt2
-rw-r--r--services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SystemStubMultiUserDisableUninstallTest.kt1
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt2
-rw-r--r--services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java24
-rw-r--r--services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java69
-rw-r--r--services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java91
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java12
-rw-r--r--tools/xmlpersistence/src/main/kotlin/Generator.kt1
146 files changed, 5193 insertions, 1973 deletions
diff --git a/core/java/android/animation/AnimationHandler.java b/core/java/android/animation/AnimationHandler.java
index 7e814af3451d..1403ba2744b3 100644
--- a/core/java/android/animation/AnimationHandler.java
+++ b/core/java/android/animation/AnimationHandler.java
@@ -432,8 +432,9 @@ public class AnimationHandler {
/**
* Callbacks that receives notifications for animation timing and frame commit timing.
+ * @hide
*/
- interface AnimationFrameCallback {
+ public interface AnimationFrameCallback {
/**
* Run animation based on the frame time.
* @param frameTime The frame start time, in the {@link SystemClock#uptimeMillis()} time
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index e022ca306674..0ea53ce52a52 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -2080,6 +2080,21 @@ public class WallpaperManager {
}
/**
+ * Set the live wallpaper for the given screen(s).
+ *
+ * This can only be called by packages with android.permission.SET_WALLPAPER_COMPONENT
+ * permission. The caller must hold the INTERACT_ACROSS_USERS_FULL permission to change
+ * another user's wallpaper.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT)
+ public boolean setWallpaperComponentWithFlags(@NonNull ComponentName name,
+ @SetWallpaperFlags int which) {
+ return setWallpaperComponent(name);
+ }
+
+ /**
* Set the display position of the current wallpaper within any larger space, when
* that wallpaper is visible behind the given window. The X and Y offsets
* are floating point numbers ranging from 0 to 1, representing where the
diff --git a/core/java/android/service/wallpaper/IWallpaperService.aidl b/core/java/android/service/wallpaper/IWallpaperService.aidl
index 56e2486dd626..f46c60fc4f7a 100644
--- a/core/java/android/service/wallpaper/IWallpaperService.aidl
+++ b/core/java/android/service/wallpaper/IWallpaperService.aidl
@@ -25,6 +25,6 @@ import android.service.wallpaper.IWallpaperConnection;
oneway interface IWallpaperService {
void attach(IWallpaperConnection connection,
IBinder windowToken, int windowType, boolean isPreview,
- int reqWidth, int reqHeight, in Rect padding, int displayId);
+ int reqWidth, int reqHeight, in Rect padding, int displayId, int which);
void detach();
}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 01749c0bebb9..e5792a9ef4e2 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -18,6 +18,7 @@ package android.service.wallpaper;
import static android.app.WallpaperManager.COMMAND_FREEZE;
import static android.app.WallpaperManager.COMMAND_UNFREEZE;
+import static android.app.WallpaperManager.SetWallpaperFlags;
import static android.graphics.Matrix.MSCALE_X;
import static android.graphics.Matrix.MSCALE_Y;
import static android.graphics.Matrix.MSKEW_X;
@@ -2427,7 +2428,7 @@ public abstract class WallpaperService extends Service {
@Override
public void attach(IWallpaperConnection conn, IBinder windowToken,
int windowType, boolean isPreview, int reqWidth, int reqHeight, Rect padding,
- int displayId) {
+ int displayId, @SetWallpaperFlags int which) {
mEngineWrapper = new IWallpaperEngineWrapper(mTarget, conn, windowToken,
windowType, isPreview, reqWidth, reqHeight, padding, displayId);
}
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
index 44f419a8097d..e407707231ca 100644
--- a/core/java/android/view/RemoteAnimationTarget.java
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -241,6 +241,8 @@ public class RemoteAnimationTarget implements Parcelable {
*/
public boolean willShowImeOnTarget;
+ public int rotationChange;
+
public RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent,
Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position,
Rect localBounds, Rect screenSpaceBounds,
@@ -302,6 +304,7 @@ public class RemoteAnimationTarget implements Parcelable {
backgroundColor = in.readInt();
showBackdrop = in.readBoolean();
willShowImeOnTarget = in.readBoolean();
+ rotationChange = in.readInt();
}
public void setShowBackdrop(boolean shouldShowBackdrop) {
@@ -316,6 +319,14 @@ public class RemoteAnimationTarget implements Parcelable {
return willShowImeOnTarget;
}
+ public void setRotationChange(int rotationChange) {
+ this.rotationChange = rotationChange;
+ }
+
+ public int getRotationChange() {
+ return rotationChange;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -345,6 +356,7 @@ public class RemoteAnimationTarget implements Parcelable {
dest.writeInt(backgroundColor);
dest.writeBoolean(showBackdrop);
dest.writeBoolean(willShowImeOnTarget);
+ dest.writeInt(rotationChange);
}
public void dump(PrintWriter pw, String prefix) {
diff --git a/core/java/com/android/internal/dynamicanimation/animation/DynamicAnimation.java b/core/java/com/android/internal/dynamicanimation/animation/DynamicAnimation.java
new file mode 100644
index 000000000000..d4fe7c8d7f36
--- /dev/null
+++ b/core/java/com/android/internal/dynamicanimation/animation/DynamicAnimation.java
@@ -0,0 +1,815 @@
+/*
+ * 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.internal.dynamicanimation.animation;
+
+import android.animation.AnimationHandler;
+import android.animation.ValueAnimator;
+import android.annotation.FloatRange;
+import android.annotation.MainThread;
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.os.Looper;
+import android.util.AndroidRuntimeException;
+import android.util.FloatProperty;
+import android.view.View;
+
+import java.util.ArrayList;
+
+/**
+ * This class is the base class of physics-based animations. It manages the animation's
+ * lifecycle such as {@link #start()} and {@link #cancel()}. This base class also handles the common
+ * setup for all the subclass animations. For example, DynamicAnimation supports adding
+ * {@link OnAnimationEndListener} and {@link OnAnimationUpdateListener} so that the important
+ * animation events can be observed through the callbacks. The start conditions for any subclass of
+ * DynamicAnimation can be set using {@link #setStartValue(float)} and
+ * {@link #setStartVelocity(float)}.
+ *
+ * @param <T> subclass of DynamicAnimation
+ */
+public abstract class DynamicAnimation<T extends DynamicAnimation<T>>
+ implements AnimationHandler.AnimationFrameCallback {
+
+ /**
+ * ViewProperty holds the access of a property of a {@link View}. When an animation is
+ * created with a {@link ViewProperty} instance, the corresponding property value of the view
+ * will be updated through this ViewProperty instance.
+ */
+ public abstract static class ViewProperty extends FloatProperty<View> {
+ private ViewProperty(String name) {
+ super(name);
+ }
+ }
+
+ /**
+ * View's translationX property.
+ */
+ public static final ViewProperty TRANSLATION_X = new ViewProperty("translationX") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setTranslationX(value);
+ }
+
+ @Override
+ public Float get(View view) {
+ return view.getTranslationX();
+ }
+ };
+
+ /**
+ * View's translationY property.
+ */
+ public static final ViewProperty TRANSLATION_Y = new ViewProperty("translationY") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setTranslationY(value);
+ }
+
+ @Override
+ public Float get(View view) {
+ return view.getTranslationY();
+ }
+ };
+
+ /**
+ * View's translationZ property.
+ */
+ public static final ViewProperty TRANSLATION_Z = new ViewProperty("translationZ") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setTranslationZ(value);
+ }
+
+ @Override
+ public Float get(View view) {
+ return view.getTranslationZ();
+ }
+ };
+
+ /**
+ * View's scaleX property.
+ */
+ public static final ViewProperty SCALE_X = new ViewProperty("scaleX") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setScaleX(value);
+ }
+
+ @Override
+ public Float get(View view) {
+ return view.getScaleX();
+ }
+ };
+
+ /**
+ * View's scaleY property.
+ */
+ public static final ViewProperty SCALE_Y = new ViewProperty("scaleY") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setScaleY(value);
+ }
+
+ @Override
+ public Float get(View view) {
+ return view.getScaleY();
+ }
+ };
+
+ /**
+ * View's rotation property.
+ */
+ public static final ViewProperty ROTATION = new ViewProperty("rotation") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setRotation(value);
+ }
+
+ @Override
+ public Float get(View view) {
+ return view.getRotation();
+ }
+ };
+
+ /**
+ * View's rotationX property.
+ */
+ public static final ViewProperty ROTATION_X = new ViewProperty("rotationX") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setRotationX(value);
+ }
+
+ @Override
+ public Float get(View view) {
+ return view.getRotationX();
+ }
+ };
+
+ /**
+ * View's rotationY property.
+ */
+ public static final ViewProperty ROTATION_Y = new ViewProperty("rotationY") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setRotationY(value);
+ }
+
+ @Override
+ public Float get(View view) {
+ return view.getRotationY();
+ }
+ };
+
+ /**
+ * View's x property.
+ */
+ public static final ViewProperty X = new ViewProperty("x") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setX(value);
+ }
+
+ @Override
+ public Float get(View view) {
+ return view.getX();
+ }
+ };
+
+ /**
+ * View's y property.
+ */
+ public static final ViewProperty Y = new ViewProperty("y") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setY(value);
+ }
+
+ @Override
+ public Float get(View view) {
+ return view.getY();
+ }
+ };
+
+ /**
+ * View's z property.
+ */
+ public static final ViewProperty Z = new ViewProperty("z") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setZ(value);
+ }
+
+ @Override
+ public Float get(View view) {
+ return view.getZ();
+ }
+ };
+
+ /**
+ * View's alpha property.
+ */
+ public static final ViewProperty ALPHA = new ViewProperty("alpha") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setAlpha(value);
+ }
+
+ @Override
+ public Float get(View view) {
+ return view.getAlpha();
+ }
+ };
+
+ // Properties below are not RenderThread compatible
+ /**
+ * View's scrollX property.
+ */
+ public static final ViewProperty SCROLL_X = new ViewProperty("scrollX") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setScrollX((int) value);
+ }
+
+ @Override
+ public Float get(View view) {
+ return (float) view.getScrollX();
+ }
+ };
+
+ /**
+ * View's scrollY property.
+ */
+ public static final ViewProperty SCROLL_Y = new ViewProperty("scrollY") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setScrollY((int) value);
+ }
+
+ @Override
+ public Float get(View view) {
+ return (float) view.getScrollY();
+ }
+ };
+
+ /**
+ * The minimum visible change in pixels that can be visible to users.
+ */
+ @SuppressLint("MinMaxConstant")
+ public static final float MIN_VISIBLE_CHANGE_PIXELS = 1f;
+ /**
+ * The minimum visible change in degrees that can be visible to users.
+ */
+ @SuppressLint("MinMaxConstant")
+ public static final float MIN_VISIBLE_CHANGE_ROTATION_DEGREES = 1f / 10f;
+ /**
+ * The minimum visible change in alpha that can be visible to users.
+ */
+ @SuppressLint("MinMaxConstant")
+ public static final float MIN_VISIBLE_CHANGE_ALPHA = 1f / 256f;
+ /**
+ * The minimum visible change in scale that can be visible to users.
+ */
+ @SuppressLint("MinMaxConstant")
+ public static final float MIN_VISIBLE_CHANGE_SCALE = 1f / 500f;
+
+ // Use the max value of float to indicate an unset state.
+ private static final float UNSET = Float.MAX_VALUE;
+
+ // Multiplier to the min visible change value for value threshold
+ private static final float THRESHOLD_MULTIPLIER = 0.75f;
+
+ // Internal tracking for velocity.
+ float mVelocity = 0;
+
+ // Internal tracking for value.
+ float mValue = UNSET;
+
+ // Tracks whether start value is set. If not, the animation will obtain the value at the time
+ // of starting through the getter and use that as the starting value of the animation.
+ boolean mStartValueIsSet = false;
+
+ // Target to be animated.
+ final Object mTarget;
+
+ // View property id.
+ final FloatProperty mProperty;
+
+ // Package private tracking of animation lifecycle state. Visible to subclass animations.
+ boolean mRunning = false;
+
+ // Min and max values that defines the range of the animation values.
+ float mMaxValue = Float.MAX_VALUE;
+ float mMinValue = -mMaxValue;
+
+ // Last frame time. Always gets reset to -1 at the end of the animation.
+ private long mLastFrameTime = 0;
+
+ private float mMinVisibleChange;
+
+ // List of end listeners
+ private final ArrayList<OnAnimationEndListener> mEndListeners = new ArrayList<>();
+
+ // List of update listeners
+ private final ArrayList<OnAnimationUpdateListener> mUpdateListeners = new ArrayList<>();
+
+ // Animation handler used to schedule updates for this animation.
+ private AnimationHandler mAnimationHandler;
+
+ // Internal state for value/velocity pair.
+ static class MassState {
+ float mValue;
+ float mVelocity;
+ }
+
+ /**
+ * Creates a dynamic animation with the given FloatValueHolder instance.
+ *
+ * @param floatValueHolder the FloatValueHolder instance to be animated.
+ */
+ DynamicAnimation(final FloatValueHolder floatValueHolder) {
+ mTarget = null;
+ mProperty = new FloatProperty("FloatValueHolder") {
+ @Override
+ public Float get(Object object) {
+ return floatValueHolder.getValue();
+ }
+
+ @Override
+ public void setValue(Object object, float value) {
+ floatValueHolder.setValue(value);
+ }
+ };
+ mMinVisibleChange = MIN_VISIBLE_CHANGE_PIXELS;
+ }
+
+ /**
+ * Creates a dynamic animation to animate the given property for the given {@link View}
+ *
+ * @param object the Object whose property is to be animated
+ * @param property the property to be animated
+ */
+
+ <K> DynamicAnimation(K object, FloatProperty<K> property) {
+ mTarget = object;
+ mProperty = property;
+ if (mProperty == ROTATION || mProperty == ROTATION_X
+ || mProperty == ROTATION_Y) {
+ mMinVisibleChange = MIN_VISIBLE_CHANGE_ROTATION_DEGREES;
+ } else if (mProperty == ALPHA) {
+ mMinVisibleChange = MIN_VISIBLE_CHANGE_ALPHA;
+ } else if (mProperty == SCALE_X || mProperty == SCALE_Y) {
+ mMinVisibleChange = MIN_VISIBLE_CHANGE_SCALE;
+ } else {
+ mMinVisibleChange = MIN_VISIBLE_CHANGE_PIXELS;
+ }
+ }
+
+ /**
+ * Sets the start value of the animation. If start value is not set, the animation will get
+ * the current value for the view's property, and use that as the start value.
+ *
+ * @param startValue start value for the animation
+ * @return the Animation whose start value is being set
+ */
+ @SuppressWarnings("unchecked")
+ public T setStartValue(float startValue) {
+ mValue = startValue;
+ mStartValueIsSet = true;
+ return (T) this;
+ }
+
+ /**
+ * Start velocity of the animation. Default velocity is 0. Unit: change in property per
+ * second (e.g. pixels per second, scale/alpha value change per second).
+ *
+ * <p>Note when using a fixed value as the start velocity (as opposed to getting the velocity
+ * through touch events), it is recommended to define such a value in dp/second and convert it
+ * to pixel/second based on the density of the screen to achieve a consistent look across
+ * different screens.
+ *
+ * <p>To convert from dp/second to pixel/second:
+ * <pre class="prettyprint">
+ * float pixelPerSecond = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpPerSecond,
+ * getResources().getDisplayMetrics());
+ * </pre>
+ *
+ * @param startVelocity start velocity of the animation
+ * @return the Animation whose start velocity is being set
+ */
+ @SuppressWarnings("unchecked")
+ public T setStartVelocity(float startVelocity) {
+ mVelocity = startVelocity;
+ return (T) this;
+ }
+
+ /**
+ * Sets the max value of the animation. Animations will not animate beyond their max value.
+ * Whether or not animation will come to an end when max value is reached is dependent on the
+ * child animation's implementation.
+ *
+ * @param max maximum value of the property to be animated
+ * @return the Animation whose max value is being set
+ */
+ @SuppressWarnings("unchecked")
+ public T setMaxValue(float max) {
+ // This max value should be checked and handled in the subclass animations, instead of
+ // assuming the end of the animations when the max/min value is hit in the base class.
+ // The reason is that hitting max/min value may just be a transient state, such as during
+ // the spring oscillation.
+ mMaxValue = max;
+ return (T) this;
+ }
+
+ /**
+ * Sets the min value of the animation. Animations will not animate beyond their min value.
+ * Whether or not animation will come to an end when min value is reached is dependent on the
+ * child animation's implementation.
+ *
+ * @param min minimum value of the property to be animated
+ * @return the Animation whose min value is being set
+ */
+ @SuppressWarnings("unchecked")
+ public T setMinValue(float min) {
+ mMinValue = min;
+ return (T) this;
+ }
+
+ /**
+ * Adds an end listener to the animation for receiving onAnimationEnd callbacks. If the listener
+ * is {@code null} or has already been added to the list of listeners for the animation, no op.
+ *
+ * @param listener the listener to be added
+ * @return the animation to which the listener is added
+ */
+ @SuppressWarnings("unchecked")
+ public T addEndListener(OnAnimationEndListener listener) {
+ if (!mEndListeners.contains(listener)) {
+ mEndListeners.add(listener);
+ }
+ return (T) this;
+ }
+
+ /**
+ * Removes the end listener from the animation, so as to stop receiving animation end callbacks.
+ *
+ * @param listener the listener to be removed
+ */
+ public void removeEndListener(OnAnimationEndListener listener) {
+ removeEntry(mEndListeners, listener);
+ }
+
+ /**
+ * Adds an update listener to the animation for receiving per-frame animation update callbacks.
+ * If the listener is {@code null} or has already been added to the list of listeners for the
+ * animation, no op.
+ *
+ * <p>Note that update listener should only be added before the start of the animation.
+ *
+ * @param listener the listener to be added
+ * @return the animation to which the listener is added
+ * @throws UnsupportedOperationException if the update listener is added after the animation has
+ * started
+ */
+ @SuppressWarnings("unchecked")
+ public T addUpdateListener(OnAnimationUpdateListener listener) {
+ if (isRunning()) {
+ // Require update listener to be added before the animation, such as when we start
+ // the animation, we know whether the animation is RenderThread compatible.
+ throw new UnsupportedOperationException("Error: Update listeners must be added before"
+ + "the animation.");
+ }
+ if (!mUpdateListeners.contains(listener)) {
+ mUpdateListeners.add(listener);
+ }
+ return (T) this;
+ }
+
+ /**
+ * Removes the update listener from the animation, so as to stop receiving animation update
+ * callbacks.
+ *
+ * @param listener the listener to be removed
+ */
+ public void removeUpdateListener(OnAnimationUpdateListener listener) {
+ removeEntry(mUpdateListeners, listener);
+ }
+
+
+ /**
+ * This method sets the minimal change of animation value that is visible to users, which helps
+ * determine a reasonable threshold for the animation's termination condition. It is critical
+ * to set the minimal visible change for custom properties (i.e. non-<code>ViewProperty</code>s)
+ * unless the custom property is in pixels.
+ *
+ * <p>For custom properties, this minimum visible change defaults to change in pixel
+ * (i.e. {@link #MIN_VISIBLE_CHANGE_PIXELS}. It is recommended to adjust this value that is
+ * reasonable for the property to be animated. A general rule of thumb to calculate such a value
+ * is: minimum visible change = range of custom property value / corresponding pixel range. For
+ * example, if the property to be animated is a progress (from 0 to 100) that corresponds to a
+ * 200-pixel change. Then the min visible change should be 100 / 200. (i.e. 0.5).
+ *
+ * <p>It's not necessary to call this method when animating {@link ViewProperty}s, as the
+ * minimum visible change will be derived from the property. For example, if the property to be
+ * animated is in pixels (i.e. {@link #TRANSLATION_X}, {@link #TRANSLATION_Y},
+ * {@link #TRANSLATION_Z}, @{@link #SCROLL_X} or {@link #SCROLL_Y}), the default minimum visible
+ * change is 1 (pixel). For {@link #ROTATION}, {@link #ROTATION_X} or {@link #ROTATION_Y}, the
+ * animation will use {@link #MIN_VISIBLE_CHANGE_ROTATION_DEGREES} as the min visible change,
+ * which is 1/10. Similarly, the minimum visible change for alpha (
+ * i.e. {@link #MIN_VISIBLE_CHANGE_ALPHA} is defined as 1 / 256.
+ *
+ * @param minimumVisibleChange minimum change in property value that is visible to users
+ * @return the animation whose min visible change is being set
+ * @throws IllegalArgumentException if the given threshold is not positive
+ */
+ @SuppressWarnings("unchecked")
+ public T setMinimumVisibleChange(@FloatRange(from = 0.0, fromInclusive = false)
+ float minimumVisibleChange) {
+ if (minimumVisibleChange <= 0) {
+ throw new IllegalArgumentException("Minimum visible change must be positive.");
+ }
+ mMinVisibleChange = minimumVisibleChange;
+ setValueThreshold(minimumVisibleChange * THRESHOLD_MULTIPLIER);
+ return (T) this;
+ }
+
+ /**
+ * Returns the minimum change in the animation property that could be visibly different to
+ * users.
+ *
+ * @return minimum change in property value that is visible to users
+ */
+ public float getMinimumVisibleChange() {
+ return mMinVisibleChange;
+ }
+
+ /**
+ * Remove {@code null} entries from the list.
+ */
+ private static <T> void removeNullEntries(ArrayList<T> list) {
+ // Clean up null entries
+ for (int i = list.size() - 1; i >= 0; i--) {
+ if (list.get(i) == null) {
+ list.remove(i);
+ }
+ }
+ }
+
+ /**
+ * Remove an entry from the list by marking it {@code null} and clean up later.
+ */
+ private static <T> void removeEntry(ArrayList<T> list, T entry) {
+ int id = list.indexOf(entry);
+ if (id >= 0) {
+ list.set(id, null);
+ }
+ }
+
+ /****************Animation Lifecycle Management***************/
+
+ /**
+ * Starts an animation. If the animation has already been started, no op. Note that calling
+ * {@link #start()} will not immediately set the property value to start value of the animation.
+ * The property values will be changed at each animation pulse, which happens before the draw
+ * pass. As a result, the changes will be reflected in the next frame, the same as if the values
+ * were set immediately. This method should only be called on main thread.
+ *
+ * Unless a AnimationHandler is provided via setAnimationHandler, a default AnimationHandler
+ * is created on the same thread as the first call to start/cancel an animation. All the
+ * subsequent animation lifecycle manipulations need to be on that same thread, until the
+ * AnimationHandler is reset (using [setAnimationHandler]).
+ *
+ * @throws AndroidRuntimeException if this method is not called on the same thread as the
+ * animation handler
+ */
+ @MainThread
+ public void start() {
+ if (!isCurrentThread()) {
+ throw new AndroidRuntimeException("Animations may only be started on the same thread "
+ + "as the animation handler");
+ }
+ if (!mRunning) {
+ startAnimationInternal();
+ }
+ }
+
+ boolean isCurrentThread() {
+ return Thread.currentThread() == Looper.myLooper().getThread();
+ }
+
+ /**
+ * Cancels the on-going animation. If the animation hasn't started, no op.
+ *
+ * Unless a AnimationHandler is provided via setAnimationHandler, a default AnimationHandler
+ * is created on the same thread as the first call to start/cancel an animation. All the
+ * subsequent animation lifecycle manipulations need to be on that same thread, until the
+ * AnimationHandler is reset (using [setAnimationHandler]).
+ *
+ * @throws AndroidRuntimeException if this method is not called on the same thread as the
+ * animation handler
+ */
+ @MainThread
+ public void cancel() {
+ if (!isCurrentThread()) {
+ throw new AndroidRuntimeException("Animations may only be canceled from the same "
+ + "thread as the animation handler");
+ }
+ if (mRunning) {
+ endAnimationInternal(true);
+ }
+ }
+
+ /**
+ * Returns whether the animation is currently running.
+ *
+ * @return {@code true} if the animation is currently running, {@code false} otherwise
+ */
+ public boolean isRunning() {
+ return mRunning;
+ }
+
+ /************************** Private APIs below ********************************/
+
+ // This gets called when the animation is started, to finish the setup of the animation
+ // before the animation pulsing starts.
+ private void startAnimationInternal() {
+ if (!mRunning) {
+ mRunning = true;
+ if (!mStartValueIsSet) {
+ mValue = getPropertyValue();
+ }
+ // Sanity check:
+ if (mValue > mMaxValue || mValue < mMinValue) {
+ throw new IllegalArgumentException("Starting value need to be in between min"
+ + " value and max value");
+ }
+ getAnimationHandler().addAnimationFrameCallback(this, 0);
+ }
+ }
+
+ /**
+ * This gets call on each frame of the animation. Animation value and velocity are updated
+ * in this method based on the new frame time. The property value of the view being animated
+ * is then updated. The animation's ending conditions are also checked in this method. Once
+ * the animation reaches equilibrium, the animation will come to its end, and end listeners
+ * will be notified, if any.
+ */
+ @Override
+ public boolean doAnimationFrame(long frameTime) {
+ if (mLastFrameTime == 0) {
+ // First frame.
+ mLastFrameTime = frameTime;
+ setPropertyValue(mValue);
+ return false;
+ }
+ long deltaT = frameTime - mLastFrameTime;
+ mLastFrameTime = frameTime;
+ float durationScale = ValueAnimator.getDurationScale();
+ deltaT = durationScale == 0.0f ? Integer.MAX_VALUE : (long) (deltaT / durationScale);
+ boolean finished = updateValueAndVelocity(deltaT);
+ // Clamp value & velocity.
+ mValue = Math.min(mValue, mMaxValue);
+ mValue = Math.max(mValue, mMinValue);
+
+ setPropertyValue(mValue);
+
+ if (finished) {
+ endAnimationInternal(false);
+ }
+ return finished;
+ }
+
+ @Override
+ public void commitAnimationFrame(long frameTime) {
+ doAnimationFrame(frameTime);
+ }
+
+ /**
+ * Updates the animation state (i.e. value and velocity). This method is package private, so
+ * subclasses can override this method to calculate the new value and velocity in their custom
+ * way.
+ *
+ * @param deltaT time elapsed in millisecond since last frame
+ * @return whether the animation has finished
+ */
+ abstract boolean updateValueAndVelocity(long deltaT);
+
+ /**
+ * Internal method to reset the animation states when animation is finished/canceled.
+ */
+ private void endAnimationInternal(boolean canceled) {
+ mRunning = false;
+ getAnimationHandler().removeCallback(this);
+ mLastFrameTime = 0;
+ mStartValueIsSet = false;
+ for (int i = 0; i < mEndListeners.size(); i++) {
+ if (mEndListeners.get(i) != null) {
+ mEndListeners.get(i).onAnimationEnd(this, canceled, mValue, mVelocity);
+ }
+ }
+ removeNullEntries(mEndListeners);
+ }
+
+ /**
+ * Updates the property value through the corresponding setter.
+ */
+ @SuppressWarnings("unchecked")
+ void setPropertyValue(float value) {
+ mProperty.setValue(mTarget, value);
+ for (int i = 0; i < mUpdateListeners.size(); i++) {
+ if (mUpdateListeners.get(i) != null) {
+ mUpdateListeners.get(i).onAnimationUpdate(this, mValue, mVelocity);
+ }
+ }
+ removeNullEntries(mUpdateListeners);
+ }
+
+ /**
+ * Returns the default threshold.
+ */
+ float getValueThreshold() {
+ return mMinVisibleChange * THRESHOLD_MULTIPLIER;
+ }
+
+ /**
+ * Obtain the property value through the corresponding getter.
+ */
+ @SuppressWarnings("unchecked")
+ private float getPropertyValue() {
+ return (Float) mProperty.get(mTarget);
+ }
+
+ /**
+ * Returns the {@link AnimationHandler} used to schedule updates for this animator.
+ *
+ * @return the {@link AnimationHandler} for this animator.
+ */
+ @NonNull
+ public AnimationHandler getAnimationHandler() {
+ return mAnimationHandler != null ? mAnimationHandler : AnimationHandler.getInstance();
+ }
+
+ /****************Sub class animations**************/
+ /**
+ * Returns the acceleration at the given value with the given velocity.
+ **/
+ abstract float getAcceleration(float value, float velocity);
+
+ /**
+ * Returns whether the animation has reached equilibrium.
+ */
+ abstract boolean isAtEquilibrium(float value, float velocity);
+
+ /**
+ * Updates the default value threshold for the animation based on the property to be animated.
+ */
+ abstract void setValueThreshold(float threshold);
+
+ /**
+ * An animation listener that receives end notifications from an animation.
+ */
+ public interface OnAnimationEndListener {
+ /**
+ * Notifies the end of an animation. Note that this callback will be invoked not only when
+ * an animation reach equilibrium, but also when the animation is canceled.
+ *
+ * @param animation animation that has ended or was canceled
+ * @param canceled whether the animation has been canceled
+ * @param value the final value when the animation stopped
+ * @param velocity the final velocity when the animation stopped
+ */
+ void onAnimationEnd(DynamicAnimation animation, boolean canceled, float value,
+ float velocity);
+ }
+
+ /**
+ * Implementors of this interface can add themselves as update listeners
+ * to an <code>DynamicAnimation</code> instance to receive callbacks on every animation
+ * frame, after the current frame's values have been calculated for that
+ * <code>DynamicAnimation</code>.
+ */
+ public interface OnAnimationUpdateListener {
+
+ /**
+ * Notifies the occurrence of another frame of the animation.
+ *
+ * @param animation animation that the update listener is added to
+ * @param value the current value of the animation
+ * @param velocity the current velocity of the animation
+ */
+ void onAnimationUpdate(DynamicAnimation animation, float value, float velocity);
+ }
+}
diff --git a/core/java/com/android/internal/dynamicanimation/animation/FloatValueHolder.java b/core/java/com/android/internal/dynamicanimation/animation/FloatValueHolder.java
new file mode 100644
index 000000000000..c3a2cacd16ec
--- /dev/null
+++ b/core/java/com/android/internal/dynamicanimation/animation/FloatValueHolder.java
@@ -0,0 +1,64 @@
+/*
+ * 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.internal.dynamicanimation.animation;
+
+/**
+ * <p>FloatValueHolder holds a float value. FloatValueHolder provides a setter and a getter (
+ * i.e. {@link #setValue(float)} and {@link #getValue()}) to access this float value. Animations can
+ * be performed on a FloatValueHolder instance. During each frame of the animation, the
+ * FloatValueHolder will have its value updated via {@link #setValue(float)}. The caller can
+ * obtain the up-to-date animation value via {@link FloatValueHolder#getValue()}.
+ *
+ * @see SpringAnimation#SpringAnimation(FloatValueHolder)
+ */
+
+public class FloatValueHolder {
+ private float mValue = 0.0f;
+
+ /**
+ * Constructs a holder for a float value that is initialized to 0.
+ */
+ public FloatValueHolder() {
+ }
+
+ /**
+ * Constructs a holder for a float value that is initialized to the input value.
+ *
+ * @param value the value to initialize the value held in the FloatValueHolder
+ */
+ public FloatValueHolder(float value) {
+ setValue(value);
+ }
+
+ /**
+ * Sets the value held in the FloatValueHolder instance.
+ *
+ * @param value float value held in the FloatValueHolder instance
+ */
+ public void setValue(float value) {
+ mValue = value;
+ }
+
+ /**
+ * Returns the float value held in the FloatValueHolder instance.
+ *
+ * @return float value held in the FloatValueHolder instance
+ */
+ public float getValue() {
+ return mValue;
+ }
+}
diff --git a/core/java/com/android/internal/dynamicanimation/animation/Force.java b/core/java/com/android/internal/dynamicanimation/animation/Force.java
new file mode 100644
index 000000000000..fcb9c459fff3
--- /dev/null
+++ b/core/java/com/android/internal/dynamicanimation/animation/Force.java
@@ -0,0 +1,27 @@
+/*
+ * 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.internal.dynamicanimation.animation;
+
+/**
+ * Hide this for now, in case we want to change the API.
+ */
+interface Force {
+ // Acceleration based on position.
+ float getAcceleration(float position, float velocity);
+
+ boolean isAtEquilibrium(float value, float velocity);
+}
diff --git a/core/java/com/android/internal/dynamicanimation/animation/SpringAnimation.java b/core/java/com/android/internal/dynamicanimation/animation/SpringAnimation.java
new file mode 100644
index 000000000000..2f3b72c4f97d
--- /dev/null
+++ b/core/java/com/android/internal/dynamicanimation/animation/SpringAnimation.java
@@ -0,0 +1,314 @@
+/*
+ * 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.internal.dynamicanimation.animation;
+
+import android.util.AndroidRuntimeException;
+import android.util.FloatProperty;
+
+/**
+ * SpringAnimation is an animation that is driven by a {@link SpringForce}. The spring force defines
+ * the spring's stiffness, damping ratio, as well as the rest position. Once the SpringAnimation is
+ * started, on each frame the spring force will update the animation's value and velocity.
+ * The animation will continue to run until the spring force reaches equilibrium. If the spring used
+ * in the animation is undamped, the animation will never reach equilibrium. Instead, it will
+ * oscillate forever.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * </div>
+ *
+ * <p>To create a simple {@link SpringAnimation} that uses the default {@link SpringForce}:</p>
+ * <pre class="prettyprint">
+ * // Create an animation to animate view's X property, set the rest position of the
+ * // default spring to 0, and start the animation with a starting velocity of 5000 (pixel/s).
+ * final SpringAnimation anim = new SpringAnimation(view, DynamicAnimation.X, 0)
+ * .setStartVelocity(5000);
+ * anim.start();
+ * </pre>
+ *
+ * <p>Alternatively, a {@link SpringAnimation} can take a pre-configured {@link SpringForce}, and
+ * use that to drive the animation. </p>
+ * <pre class="prettyprint">
+ * // Create a low stiffness, low bounce spring at position 0.
+ * SpringForce spring = new SpringForce(0)
+ * .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)
+ * .setStiffness(SpringForce.STIFFNESS_LOW);
+ * // Create an animation to animate view's scaleY property, and start the animation using
+ * // the spring above and a starting value of 0.5. Additionally, constrain the range of value for
+ * // the animation to be non-negative, effectively preventing any spring overshoot.
+ * final SpringAnimation anim = new SpringAnimation(view, DynamicAnimation.SCALE_Y)
+ * .setMinValue(0).setSpring(spring).setStartValue(1);
+ * anim.start();
+ * </pre>
+ */
+public final class SpringAnimation extends DynamicAnimation<SpringAnimation> {
+
+ private SpringForce mSpring = null;
+ private float mPendingPosition = UNSET;
+ private static final float UNSET = Float.MAX_VALUE;
+ private boolean mEndRequested = false;
+
+ /**
+ * <p>This creates a SpringAnimation that animates a {@link FloatValueHolder} instance. During
+ * the animation, the {@link FloatValueHolder} instance will be updated via
+ * {@link FloatValueHolder#setValue(float)} each frame. The caller can obtain the up-to-date
+ * animation value via {@link FloatValueHolder#getValue()}.
+ *
+ * <p><strong>Note:</strong> changing the value in the {@link FloatValueHolder} via
+ * {@link FloatValueHolder#setValue(float)} outside of the animation during an
+ * animation run will not have any effect on the on-going animation.
+ *
+ * @param floatValueHolder the property to be animated
+ */
+ public SpringAnimation(FloatValueHolder floatValueHolder) {
+ super(floatValueHolder);
+ }
+
+ /**
+ * <p>This creates a SpringAnimation that animates a {@link FloatValueHolder} instance. During
+ * the animation, the {@link FloatValueHolder} instance will be updated via
+ * {@link FloatValueHolder#setValue(float)} each frame. The caller can obtain the up-to-date
+ * animation value via {@link FloatValueHolder#getValue()}.
+ *
+ * A Spring will be created with the given final position and default stiffness and damping
+ * ratio. This spring can be accessed and reconfigured through {@link #setSpring(SpringForce)}.
+ *
+ * <p><strong>Note:</strong> changing the value in the {@link FloatValueHolder} via
+ * {@link FloatValueHolder#setValue(float)} outside of the animation during an
+ * animation run will not have any effect on the on-going animation.
+ *
+ * @param floatValueHolder the property to be animated
+ * @param finalPosition the final position of the spring to be created.
+ */
+ public SpringAnimation(FloatValueHolder floatValueHolder, float finalPosition) {
+ super(floatValueHolder);
+ mSpring = new SpringForce(finalPosition);
+ }
+
+ /**
+ * This creates a SpringAnimation that animates the property of the given object.
+ * Note, a spring will need to setup through {@link #setSpring(SpringForce)} before
+ * the animation starts.
+ *
+ * @param object the Object whose property will be animated
+ * @param property the property to be animated
+ * @param <K> the class on which the Property is declared
+ */
+ public <K> SpringAnimation(K object, FloatProperty<K> property) {
+ super(object, property);
+ }
+
+ /**
+ * This creates a SpringAnimation that animates the property of the given object. A Spring will
+ * be created with the given final position and default stiffness and damping ratio.
+ * This spring can be accessed and reconfigured through {@link #setSpring(SpringForce)}.
+ *
+ * @param object the Object whose property will be animated
+ * @param property the property to be animated
+ * @param finalPosition the final position of the spring to be created.
+ * @param <K> the class on which the Property is declared
+ */
+ public <K> SpringAnimation(K object, FloatProperty<K> property,
+ float finalPosition) {
+ super(object, property);
+ mSpring = new SpringForce(finalPosition);
+ }
+
+ /**
+ * Returns the spring that the animation uses for animations.
+ *
+ * @return the spring that the animation uses for animations
+ */
+ public SpringForce getSpring() {
+ return mSpring;
+ }
+
+ /**
+ * Uses the given spring as the force that drives this animation. If this spring force has its
+ * parameters re-configured during the animation, the new configuration will be reflected in the
+ * animation immediately.
+ *
+ * @param force a pre-defined spring force that drives the animation
+ * @return the animation that the spring force is set on
+ */
+ public SpringAnimation setSpring(SpringForce force) {
+ mSpring = force;
+ return this;
+ }
+
+ @Override
+ public void start() {
+ sanityCheck();
+ mSpring.setValueThreshold(getValueThreshold());
+ super.start();
+ }
+
+ /**
+ * Updates the final position of the spring.
+ * <p/>
+ * When the animation is running, calling this method would assume the position change of the
+ * spring as a continuous movement since last frame, which yields more accurate results than
+ * changing the spring position directly through {@link SpringForce#setFinalPosition(float)}.
+ * <p/>
+ * If the animation hasn't started, calling this method will change the spring position, and
+ * immediately start the animation.
+ *
+ * @param finalPosition rest position of the spring
+ */
+ public void animateToFinalPosition(float finalPosition) {
+ if (isRunning()) {
+ mPendingPosition = finalPosition;
+ } else {
+ if (mSpring == null) {
+ mSpring = new SpringForce(finalPosition);
+ }
+ mSpring.setFinalPosition(finalPosition);
+ start();
+ }
+ }
+
+ /**
+ * Cancels the on-going animation. If the animation hasn't started, no op. Note that this method
+ * should only be called on main thread.
+ *
+ * @throws AndroidRuntimeException if this method is not called on the main thread
+ */
+ @Override
+ public void cancel() {
+ super.cancel();
+ if (mPendingPosition != UNSET) {
+ if (mSpring == null) {
+ mSpring = new SpringForce(mPendingPosition);
+ } else {
+ mSpring.setFinalPosition(mPendingPosition);
+ }
+ mPendingPosition = UNSET;
+ }
+ }
+
+ /**
+ * Skips to the end of the animation. If the spring is undamped, an
+ * {@link IllegalStateException} will be thrown, as the animation would never reach to an end.
+ * It is recommended to check {@link #canSkipToEnd()} before calling this method. If animation
+ * is not running, no-op.
+ *
+ * Unless a AnimationHandler is provided via setAnimationHandler, a default AnimationHandler
+ * is created on the same thread as the first call to start/cancel an animation. All the
+ * subsequent animation lifecycle manipulations need to be on that same thread, until the
+ * AnimationHandler is reset (using [setAnimationHandler]).
+ *
+ * @throws IllegalStateException if the spring is undamped (i.e. damping ratio = 0)
+ * @throws AndroidRuntimeException if this method is not called on the same thread as the
+ * animation handler
+ */
+ public void skipToEnd() {
+ if (!canSkipToEnd()) {
+ throw new UnsupportedOperationException("Spring animations can only come to an end"
+ + " when there is damping");
+ }
+ if (!isCurrentThread()) {
+ throw new AndroidRuntimeException("Animations may only be started on the same thread "
+ + "as the animation handler");
+ }
+ if (mRunning) {
+ mEndRequested = true;
+ }
+ }
+
+ /**
+ * Queries whether the spring can eventually come to the rest position.
+ *
+ * @return {@code true} if the spring is damped, otherwise {@code false}
+ */
+ public boolean canSkipToEnd() {
+ return mSpring.mDampingRatio > 0;
+ }
+
+ /************************ Below are private APIs *************************/
+
+ private void sanityCheck() {
+ if (mSpring == null) {
+ throw new UnsupportedOperationException("Incomplete SpringAnimation: Either final"
+ + " position or a spring force needs to be set.");
+ }
+ double finalPosition = mSpring.getFinalPosition();
+ if (finalPosition > mMaxValue) {
+ throw new UnsupportedOperationException("Final position of the spring cannot be greater"
+ + " than the max value.");
+ } else if (finalPosition < mMinValue) {
+ throw new UnsupportedOperationException("Final position of the spring cannot be less"
+ + " than the min value.");
+ }
+ }
+
+ @Override
+ boolean updateValueAndVelocity(long deltaT) {
+ // If user had requested end, then update the value and velocity to end state and consider
+ // animation done.
+ if (mEndRequested) {
+ if (mPendingPosition != UNSET) {
+ mSpring.setFinalPosition(mPendingPosition);
+ mPendingPosition = UNSET;
+ }
+ mValue = mSpring.getFinalPosition();
+ mVelocity = 0;
+ mEndRequested = false;
+ return true;
+ }
+
+ if (mPendingPosition != UNSET) {
+ // Approximate by considering half of the time spring position stayed at the old
+ // position, half of the time it's at the new position.
+ MassState massState = mSpring.updateValues(mValue, mVelocity, deltaT / 2);
+ mSpring.setFinalPosition(mPendingPosition);
+ mPendingPosition = UNSET;
+
+ massState = mSpring.updateValues(massState.mValue, massState.mVelocity, deltaT / 2);
+ mValue = massState.mValue;
+ mVelocity = massState.mVelocity;
+
+ } else {
+ MassState massState = mSpring.updateValues(mValue, mVelocity, deltaT);
+ mValue = massState.mValue;
+ mVelocity = massState.mVelocity;
+ }
+
+ mValue = Math.max(mValue, mMinValue);
+ mValue = Math.min(mValue, mMaxValue);
+
+ if (isAtEquilibrium(mValue, mVelocity)) {
+ mValue = mSpring.getFinalPosition();
+ mVelocity = 0f;
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ float getAcceleration(float value, float velocity) {
+ return mSpring.getAcceleration(value, velocity);
+ }
+
+ @Override
+ boolean isAtEquilibrium(float value, float velocity) {
+ return mSpring.isAtEquilibrium(value, velocity);
+ }
+
+ @Override
+ void setValueThreshold(float threshold) {
+ }
+}
diff --git a/core/java/com/android/internal/dynamicanimation/animation/SpringForce.java b/core/java/com/android/internal/dynamicanimation/animation/SpringForce.java
new file mode 100644
index 000000000000..36242ae2cf3d
--- /dev/null
+++ b/core/java/com/android/internal/dynamicanimation/animation/SpringForce.java
@@ -0,0 +1,323 @@
+/*
+ * 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.internal.dynamicanimation.animation;
+
+import android.annotation.FloatRange;
+
+/**
+ * Spring Force defines the characteristics of the spring being used in the animation.
+ * <p>
+ * By configuring the stiffness and damping ratio, callers can create a spring with the look and
+ * feel suits their use case. Stiffness corresponds to the spring constant. The stiffer the spring
+ * is, the harder it is to stretch it, the faster it undergoes dampening.
+ * <p>
+ * Spring damping ratio describes how oscillations in a system decay after a disturbance.
+ * When damping ratio > 1* (i.e. over-damped), the object will quickly return to the rest position
+ * without overshooting. If damping ratio equals to 1 (i.e. critically damped), the object will
+ * return to equilibrium within the shortest amount of time. When damping ratio is less than 1
+ * (i.e. under-damped), the mass tends to overshoot, and return, and overshoot again. Without any
+ * damping (i.e. damping ratio = 0), the mass will oscillate forever.
+ */
+public final class SpringForce implements Force {
+ /**
+ * Stiffness constant for extremely stiff spring.
+ */
+ public static final float STIFFNESS_HIGH = 10_000f;
+ /**
+ * Stiffness constant for medium stiff spring. This is the default stiffness for spring force.
+ */
+ public static final float STIFFNESS_MEDIUM = 1500f;
+ /**
+ * Stiffness constant for a spring with low stiffness.
+ */
+ public static final float STIFFNESS_LOW = 200f;
+ /**
+ * Stiffness constant for a spring with very low stiffness.
+ */
+ public static final float STIFFNESS_VERY_LOW = 50f;
+
+ /**
+ * Damping ratio for a very bouncy spring. Note for under-damped springs
+ * (i.e. damping ratio < 1), the lower the damping ratio, the more bouncy the spring.
+ */
+ public static final float DAMPING_RATIO_HIGH_BOUNCY = 0.2f;
+ /**
+ * Damping ratio for a medium bouncy spring. This is also the default damping ratio for spring
+ * force. Note for under-damped springs (i.e. damping ratio < 1), the lower the damping ratio,
+ * the more bouncy the spring.
+ */
+ public static final float DAMPING_RATIO_MEDIUM_BOUNCY = 0.5f;
+ /**
+ * Damping ratio for a spring with low bounciness. Note for under-damped springs
+ * (i.e. damping ratio < 1), the lower the damping ratio, the higher the bounciness.
+ */
+ public static final float DAMPING_RATIO_LOW_BOUNCY = 0.75f;
+ /**
+ * Damping ratio for a spring with no bounciness. This damping ratio will create a critically
+ * damped spring that returns to equilibrium within the shortest amount of time without
+ * oscillating.
+ */
+ public static final float DAMPING_RATIO_NO_BOUNCY = 1f;
+
+ // This multiplier is used to calculate the velocity threshold given a certain value threshold.
+ // The idea is that if it takes >= 1 frame to move the value threshold amount, then the velocity
+ // is a reasonable threshold.
+ private static final double VELOCITY_THRESHOLD_MULTIPLIER = 1000.0 / 16.0;
+
+ // Natural frequency
+ double mNaturalFreq = Math.sqrt(STIFFNESS_MEDIUM);
+ // Damping ratio.
+ double mDampingRatio = DAMPING_RATIO_MEDIUM_BOUNCY;
+
+ // Value to indicate an unset state.
+ private static final double UNSET = Double.MAX_VALUE;
+
+ // Indicates whether the spring has been initialized
+ private boolean mInitialized = false;
+
+ // Threshold for velocity and value to determine when it's reasonable to assume that the spring
+ // is approximately at rest.
+ private double mValueThreshold;
+ private double mVelocityThreshold;
+
+ // Intermediate values to simplify the spring function calculation per frame.
+ private double mGammaPlus;
+ private double mGammaMinus;
+ private double mDampedFreq;
+
+ // Final position of the spring. This must be set before the start of the animation.
+ private double mFinalPosition = UNSET;
+
+ // Internal state to hold a value/velocity pair.
+ private final DynamicAnimation.MassState mMassState = new DynamicAnimation.MassState();
+
+ /**
+ * Creates a spring force. Note that final position of the spring must be set through
+ * {@link #setFinalPosition(float)} before the spring animation starts.
+ */
+ public SpringForce() {
+ // No op.
+ }
+
+ /**
+ * Creates a spring with a given final rest position.
+ *
+ * @param finalPosition final position of the spring when it reaches equilibrium
+ */
+ public SpringForce(float finalPosition) {
+ mFinalPosition = finalPosition;
+ }
+
+ /**
+ * Sets the stiffness of a spring. The more stiff a spring is, the more force it applies to
+ * the object attached when the spring is not at the final position. Default stiffness is
+ * {@link #STIFFNESS_MEDIUM}.
+ *
+ * @param stiffness non-negative stiffness constant of a spring
+ * @return the spring force that the given stiffness is set on
+ * @throws IllegalArgumentException if the given spring stiffness is not positive
+ */
+ public SpringForce setStiffness(
+ @FloatRange(from = 0.0, fromInclusive = false) float stiffness) {
+ if (stiffness <= 0) {
+ throw new IllegalArgumentException("Spring stiffness constant must be positive.");
+ }
+ mNaturalFreq = Math.sqrt(stiffness);
+ // All the intermediate values need to be recalculated.
+ mInitialized = false;
+ return this;
+ }
+
+ /**
+ * Gets the stiffness of the spring.
+ *
+ * @return the stiffness of the spring
+ */
+ public float getStiffness() {
+ return (float) (mNaturalFreq * mNaturalFreq);
+ }
+
+ /**
+ * Spring damping ratio describes how oscillations in a system decay after a disturbance.
+ * <p>
+ * When damping ratio > 1 (over-damped), the object will quickly return to the rest position
+ * without overshooting. If damping ratio equals to 1 (i.e. critically damped), the object will
+ * return to equilibrium within the shortest amount of time. When damping ratio is less than 1
+ * (i.e. under-damped), the mass tends to overshoot, and return, and overshoot again. Without
+ * any damping (i.e. damping ratio = 0), the mass will oscillate forever.
+ * <p>
+ * Default damping ratio is {@link #DAMPING_RATIO_MEDIUM_BOUNCY}.
+ *
+ * @param dampingRatio damping ratio of the spring, it should be non-negative
+ * @return the spring force that the given damping ratio is set on
+ * @throws IllegalArgumentException if the {@param dampingRatio} is negative.
+ */
+ public SpringForce setDampingRatio(@FloatRange(from = 0.0) float dampingRatio) {
+ if (dampingRatio < 0) {
+ throw new IllegalArgumentException("Damping ratio must be non-negative");
+ }
+ mDampingRatio = dampingRatio;
+ // All the intermediate values need to be recalculated.
+ mInitialized = false;
+ return this;
+ }
+
+ /**
+ * Returns the damping ratio of the spring.
+ *
+ * @return damping ratio of the spring
+ */
+ public float getDampingRatio() {
+ return (float) mDampingRatio;
+ }
+
+ /**
+ * Sets the rest position of the spring.
+ *
+ * @param finalPosition rest position of the spring
+ * @return the spring force that the given final position is set on
+ */
+ public SpringForce setFinalPosition(float finalPosition) {
+ mFinalPosition = finalPosition;
+ return this;
+ }
+
+ /**
+ * Returns the rest position of the spring.
+ *
+ * @return rest position of the spring
+ */
+ public float getFinalPosition() {
+ return (float) mFinalPosition;
+ }
+
+ /*********************** Below are private APIs *********************/
+
+ @Override
+ public float getAcceleration(float lastDisplacement, float lastVelocity) {
+
+ lastDisplacement -= getFinalPosition();
+
+ double k = mNaturalFreq * mNaturalFreq;
+ double c = 2 * mNaturalFreq * mDampingRatio;
+
+ return (float) (-k * lastDisplacement - c * lastVelocity);
+ }
+
+ @Override
+ public boolean isAtEquilibrium(float value, float velocity) {
+ if (Math.abs(velocity) < mVelocityThreshold
+ && Math.abs(value - getFinalPosition()) < mValueThreshold) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Initialize the string by doing the necessary pre-calculation as well as some sanity check
+ * on the setup.
+ *
+ * @throws IllegalStateException if the final position is not yet set by the time the spring
+ * animation has started
+ */
+ private void init() {
+ if (mInitialized) {
+ return;
+ }
+
+ if (mFinalPosition == UNSET) {
+ throw new IllegalStateException("Error: Final position of the spring must be"
+ + " set before the animation starts");
+ }
+
+ if (mDampingRatio > 1) {
+ // Over damping
+ mGammaPlus = -mDampingRatio * mNaturalFreq
+ + mNaturalFreq * Math.sqrt(mDampingRatio * mDampingRatio - 1);
+ mGammaMinus = -mDampingRatio * mNaturalFreq
+ - mNaturalFreq * Math.sqrt(mDampingRatio * mDampingRatio - 1);
+ } else if (mDampingRatio >= 0 && mDampingRatio < 1) {
+ // Under damping
+ mDampedFreq = mNaturalFreq * Math.sqrt(1 - mDampingRatio * mDampingRatio);
+ }
+
+ mInitialized = true;
+ }
+
+ /**
+ * Internal only call for Spring to calculate the spring position/velocity using
+ * an analytical approach.
+ */
+ DynamicAnimation.MassState updateValues(double lastDisplacement, double lastVelocity,
+ long timeElapsed) {
+ init();
+
+ double deltaT = timeElapsed / 1000d; // unit: seconds
+ lastDisplacement -= mFinalPosition;
+ double displacement;
+ double currentVelocity;
+ if (mDampingRatio > 1) {
+ // Overdamped
+ double coeffA = lastDisplacement - (mGammaMinus * lastDisplacement - lastVelocity)
+ / (mGammaMinus - mGammaPlus);
+ double coeffB = (mGammaMinus * lastDisplacement - lastVelocity)
+ / (mGammaMinus - mGammaPlus);
+ displacement = coeffA * Math.pow(Math.E, mGammaMinus * deltaT)
+ + coeffB * Math.pow(Math.E, mGammaPlus * deltaT);
+ currentVelocity = coeffA * mGammaMinus * Math.pow(Math.E, mGammaMinus * deltaT)
+ + coeffB * mGammaPlus * Math.pow(Math.E, mGammaPlus * deltaT);
+ } else if (mDampingRatio == 1) {
+ // Critically damped
+ double coeffA = lastDisplacement;
+ double coeffB = lastVelocity + mNaturalFreq * lastDisplacement;
+ displacement = (coeffA + coeffB * deltaT) * Math.pow(Math.E, -mNaturalFreq * deltaT);
+ currentVelocity = (coeffA + coeffB * deltaT) * Math.pow(Math.E, -mNaturalFreq * deltaT)
+ * -mNaturalFreq + coeffB * Math.pow(Math.E, -mNaturalFreq * deltaT);
+ } else {
+ // Underdamped
+ double cosCoeff = lastDisplacement;
+ double sinCoeff = (1 / mDampedFreq) * (mDampingRatio * mNaturalFreq
+ * lastDisplacement + lastVelocity);
+ displacement = Math.pow(Math.E, -mDampingRatio * mNaturalFreq * deltaT)
+ * (cosCoeff * Math.cos(mDampedFreq * deltaT)
+ + sinCoeff * Math.sin(mDampedFreq * deltaT));
+ currentVelocity = displacement * -mNaturalFreq * mDampingRatio
+ + Math.pow(Math.E, -mDampingRatio * mNaturalFreq * deltaT)
+ * (-mDampedFreq * cosCoeff * Math.sin(mDampedFreq * deltaT)
+ + mDampedFreq * sinCoeff * Math.cos(mDampedFreq * deltaT));
+ }
+
+ mMassState.mValue = (float) (displacement + mFinalPosition);
+ mMassState.mVelocity = (float) currentVelocity;
+ return mMassState;
+ }
+
+ /**
+ * This threshold defines how close the animation value needs to be before the animation can
+ * finish. This default value is based on the property being animated, e.g. animations on alpha,
+ * scale, translation or rotation would have different thresholds. This value should be small
+ * enough to avoid visual glitch of "jumping to the end". But it shouldn't be so small that
+ * animations take seconds to finish.
+ *
+ * @param threshold the difference between the animation value and final spring position that
+ * is allowed to end the animation when velocity is very low
+ */
+ void setValueThreshold(double threshold) {
+ mValueThreshold = Math.abs(threshold);
+ mVelocityThreshold = mValueThreshold * VELOCITY_THRESHOLD_MULTIPLIER;
+ }
+}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a9799f243cb7..41256b86bf06 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2479,6 +2479,8 @@
<integer name="config_attentionMaximumExtension">900000</integer> <!-- 15 minutes. -->
<!-- Is the system user the only user allowed to dream. -->
<bool name="config_dreamsOnlyEnabledForSystemUser">false</bool>
+ <!-- Whether dreams are disabled when ambient mode is suppressed. -->
+ <bool name="config_dreamsDisabledByAmbientModeSuppressionConfig">false</bool>
<!-- Whether to dismiss the active dream when an activity is started. Doesn't apply to
assistant activities (ACTIVITY_TYPE_ASSISTANT) -->
@@ -5956,4 +5958,8 @@
TODO(b/236022708) Move rear display state to device state config file
-->
<integer name="config_deviceStateRearDisplay">-1</integer>
+
+ <!-- Whether the lock screen is allowed to run its own live wallpaper,
+ different from the home screen wallpaper. -->
+ <bool name="config_independentLockscreenLiveWallpaper">false</bool>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 97105d80bf79..5897e3af67fc 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2235,6 +2235,7 @@
<java-symbol type="integer" name="config_dreamsBatteryLevelMinimumWhenNotPowered" />
<java-symbol type="integer" name="config_dreamsBatteryLevelDrainCutoff" />
<java-symbol type="string" name="config_dreamsDefaultComponent" />
+ <java-symbol type="bool" name="config_dreamsDisabledByAmbientModeSuppressionConfig" />
<java-symbol type="bool" name="config_dreamsOnlyEnabledForSystemUser" />
<java-symbol type="array" name="config_supportedDreamComplications" />
<java-symbol type="array" name="config_disabledDreamComponents" />
@@ -4846,6 +4847,7 @@
<java-symbol type="array" name="config_deviceStatesAvailableForAppRequests" />
<java-symbol type="array" name="config_serviceStateLocationAllowedPackages" />
<java-symbol type="integer" name="config_deviceStateRearDisplay"/>
+ <java-symbol type="bool" name="config_independentLockscreenLiveWallpaper"/>
<!-- For app language picker -->
<java-symbol type="string" name="system_locale_title" />
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 1174b685e92c..bf7326a5b30e 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -20,10 +20,11 @@ import static android.app.ActivityManager.START_SUCCESS;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_OPEN;
import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_OP_TYPE;
import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_TASK_FRAGMENT_INFO;
import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_THROWABLE;
-import static android.window.TaskFragmentOrganizer.getTransitionType;
import static android.window.TaskFragmentTransaction.TYPE_ACTIVITY_REPARENTED_TO_TASK;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_APPEARED;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_ERROR;
@@ -76,6 +77,7 @@ import androidx.annotation.Nullable;
import androidx.window.common.CommonFoldingFeature;
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
import androidx.window.extensions.WindowExtensionsProvider;
+import androidx.window.extensions.embedding.TransactionManager.TransactionRecord;
import androidx.window.extensions.layout.WindowLayoutComponentImpl;
import com.android.internal.annotations.VisibleForTesting;
@@ -100,6 +102,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
@GuardedBy("mLock")
final SplitPresenter mPresenter;
+ @VisibleForTesting
+ @GuardedBy("mLock")
+ final TransactionManager mTransactionManager;
+
// Currently applied split configuration.
@GuardedBy("mLock")
private final List<EmbeddingRule> mSplitRules = new ArrayList<>();
@@ -150,6 +156,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
final MainThreadExecutor executor = new MainThreadExecutor();
mHandler = executor.mHandler;
mPresenter = new SplitPresenter(executor, this);
+ mTransactionManager = new TransactionManager(mPresenter);
final ActivityThread activityThread = ActivityThread.currentActivityThread();
final Application application = activityThread.getApplication();
// Register a callback to be notified about activities being created.
@@ -167,7 +174,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
@Override
public void accept(List<CommonFoldingFeature> foldingFeatures) {
synchronized (mLock) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
+ final TransactionRecord transactionRecord = mTransactionManager
+ .startNewTransaction();
+ final WindowContainerTransaction wct = transactionRecord.getTransaction();
for (int i = 0; i < mTaskContainers.size(); i++) {
final TaskContainer taskContainer = mTaskContainers.valueAt(i);
if (!taskContainer.isVisible()) {
@@ -186,7 +195,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
updateContainersInTask(wct, taskContainer);
updateAnimationOverride(taskContainer);
}
- mPresenter.applyTransaction(wct);
+ // The WCT should be applied and merged to the device state change transition if
+ // there is one.
+ transactionRecord.apply(false /* shouldApplyIndependently */);
}
}
}
@@ -256,7 +267,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
@Override
public void onTransactionReady(@NonNull TaskFragmentTransaction transaction) {
synchronized (mLock) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
+ final TransactionRecord transactionRecord = mTransactionManager.startNewTransaction(
+ transaction.getTransactionToken());
+ final WindowContainerTransaction wct = transactionRecord.getTransaction();
final List<TaskFragmentTransaction.Change> changes = transaction.getChanges();
for (TaskFragmentTransaction.Change change : changes) {
final int taskId = change.getTaskId();
@@ -307,8 +320,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// Notify the server, and the server should apply and merge the
// WindowContainerTransaction to the active sync to finish the TaskFragmentTransaction.
- mPresenter.onTransactionHandled(transaction.getTransactionToken(), wct,
- getTransitionType(wct), false /* shouldApplyIndependently */);
+ transactionRecord.apply(false /* shouldApplyIndependently */);
updateCallbackIfNecessary();
}
}
@@ -333,6 +345,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
container.setInfo(wct, taskFragmentInfo);
if (container.isFinished()) {
+ mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE);
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
} else {
// Update with the latest Task configuration.
@@ -368,15 +381,18 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// Do not finish the dependents if the last activity is reparented to PiP.
// Instead, the original split should be cleanup, and the dependent may be
// expanded to fullscreen.
+ mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE);
cleanupForEnterPip(wct, container);
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
} else if (taskFragmentInfo.isTaskClearedForReuse()) {
// Do not finish the dependents if this TaskFragment was cleared due to
// launching activity in the Task.
+ mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE);
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
} else if (!container.isWaitingActivityAppear()) {
// Do not finish the container before the expected activity appear until
// timeout.
+ mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE);
mPresenter.cleanupContainer(wct, container, true /* shouldFinishDependent */);
}
} else if (wasInPip && isInPip) {
@@ -571,6 +587,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
container.setInfo(wct, taskFragmentInfo);
container.clearPendingAppearedActivities();
if (container.isEmpty()) {
+ mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE);
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
}
break;
@@ -1009,11 +1026,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
*/
@GuardedBy("mLock")
void onTaskFragmentAppearEmptyTimeout(@NonNull TaskFragmentContainer container) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- onTaskFragmentAppearEmptyTimeout(wct, container);
+ final TransactionRecord transactionRecord = mTransactionManager.startNewTransaction();
+ onTaskFragmentAppearEmptyTimeout(transactionRecord.getTransaction(), container);
// Can be applied independently as a timeout callback.
- mPresenter.applyTransaction(wct, getTransitionType(wct),
- true /* shouldApplyIndependently */);
+ transactionRecord.apply(true /* shouldApplyIndependently */);
}
/**
@@ -1023,6 +1039,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
@GuardedBy("mLock")
void onTaskFragmentAppearEmptyTimeout(@NonNull WindowContainerTransaction wct,
@NonNull TaskFragmentContainer container) {
+ mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE);
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
}
@@ -1562,6 +1579,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
* @param isOnCreated whether this happens during the primary activity onCreated.
*/
@VisibleForTesting
+ @GuardedBy("mLock")
@Nullable
Bundle getPlaceholderOptions(@NonNull Activity primaryActivity, boolean isOnCreated) {
// Setting avoid move to front will also skip the animation. We only want to do that when
@@ -1569,6 +1587,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// Check if the primary is resumed or if this is called when the primary is onCreated
// (not resumed yet).
if (isOnCreated || primaryActivity.isResumed()) {
+ // Only set trigger type if the launch happens in foreground.
+ mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_OPEN);
return null;
}
final ActivityOptions options = ActivityOptions.makeBasic();
@@ -1595,6 +1615,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
if (SplitPresenter.shouldShowSplit(splitAttributes)) {
return false;
}
+
+ mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE);
mPresenter.cleanupContainer(wct, splitContainer.getSecondaryContainer(),
false /* shouldFinishDependent */);
return true;
@@ -1905,23 +1927,26 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// that we don't launch it if an activity itself already requested something to be
// launched to side.
synchronized (mLock) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- SplitController.this.onActivityCreated(wct, activity);
+ final TransactionRecord transactionRecord = mTransactionManager
+ .startNewTransaction();
+ transactionRecord.setOriginType(TRANSIT_OPEN);
+ SplitController.this.onActivityCreated(transactionRecord.getTransaction(),
+ activity);
// The WCT should be applied and merged to the activity launch transition.
- mPresenter.applyTransaction(wct, getTransitionType(wct),
- false /* shouldApplyIndependently */);
+ transactionRecord.apply(false /* shouldApplyIndependently */);
}
}
@Override
public void onActivityConfigurationChanged(@NonNull Activity activity) {
synchronized (mLock) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- SplitController.this.onActivityConfigurationChanged(wct, activity);
+ final TransactionRecord transactionRecord = mTransactionManager
+ .startNewTransaction();
+ SplitController.this.onActivityConfigurationChanged(
+ transactionRecord.getTransaction(), activity);
// The WCT should be applied and merged to the Task change transition so that the
// placeholder is launched in the same transition.
- mPresenter.applyTransaction(wct, getTransitionType(wct),
- false /* shouldApplyIndependently */);
+ transactionRecord.apply(false /* shouldApplyIndependently */);
}
}
@@ -1977,7 +2002,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
}
synchronized (mLock) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
+ final TransactionRecord transactionRecord = mTransactionManager
+ .startNewTransaction();
+ transactionRecord.setOriginType(TRANSIT_OPEN);
+ final WindowContainerTransaction wct = transactionRecord.getTransaction();
final TaskFragmentContainer launchedInTaskFragment;
if (launchingActivity != null) {
final int taskId = getTaskId(launchingActivity);
@@ -1990,13 +2018,14 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
if (launchedInTaskFragment != null) {
// Make sure the WCT is applied immediately instead of being queued so that the
// TaskFragment will be ready before activity attachment.
- mPresenter.applyTransaction(wct, getTransitionType(wct),
- false /* shouldApplyIndependently */);
+ transactionRecord.apply(false /* shouldApplyIndependently */);
// Amend the request to let the WM know that the activity should be placed in
// the dedicated container.
options.putBinder(ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN,
launchedInTaskFragment.getTaskFragmentToken());
mCurrentIntent = intent;
+ } else {
+ transactionRecord.abort();
}
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TransactionManager.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TransactionManager.java
new file mode 100644
index 000000000000..0071fea41aa8
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TransactionManager.java
@@ -0,0 +1,201 @@
+/*
+ * 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 android.view.WindowManager.TRANSIT_CHANGE;
+import static android.view.WindowManager.TRANSIT_NONE;
+
+import android.os.IBinder;
+import android.view.WindowManager.TransitionType;
+import android.window.TaskFragmentOrganizer;
+import android.window.WindowContainerTransaction;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Responsible for managing the current {@link WindowContainerTransaction} as a response to device
+ * state changes and app interactions.
+ *
+ * A typical use flow:
+ * 1. Call {@link #startNewTransaction} to start tracking the changes.
+ * 2. Use {@link TransactionRecord#setOriginType(int)} (int)} to record the type of operation that
+ * will start a new transition on system server.
+ * 3. Use {@link #getCurrentTransactionRecord()} to get current {@link TransactionRecord} for
+ * changes.
+ * 4. Call {@link TransactionRecord#apply(boolean)} to request the system server to apply changes in
+ * the current {@link WindowContainerTransaction}, or call {@link TransactionRecord#abort()} to
+ * dispose the current one.
+ *
+ * Note:
+ * There should be only one transaction at a time. The caller should not call
+ * {@link #startNewTransaction} again before calling {@link TransactionRecord#apply(boolean)} or
+ * {@link TransactionRecord#abort()} to the previous transaction.
+ */
+class TransactionManager {
+
+ @NonNull
+ private final TaskFragmentOrganizer mOrganizer;
+
+ @Nullable
+ private TransactionRecord mCurrentTransaction;
+
+ TransactionManager(@NonNull TaskFragmentOrganizer organizer) {
+ mOrganizer = organizer;
+ }
+
+ @NonNull
+ TransactionRecord startNewTransaction() {
+ return startNewTransaction(null /* taskFragmentTransactionToken */);
+ }
+
+ /**
+ * Starts tracking the changes in a new {@link WindowContainerTransaction}. Caller can call
+ * {@link #getCurrentTransactionRecord()} later to continue adding change to the current
+ * transaction until {@link TransactionRecord#apply(boolean)} or
+ * {@link TransactionRecord#abort()} is called.
+ * @param taskFragmentTransactionToken {@link android.window.TaskFragmentTransaction
+ * #getTransactionToken()} if this is a response to a
+ * {@link android.window.TaskFragmentTransaction}.
+ */
+ @NonNull
+ TransactionRecord startNewTransaction(@Nullable IBinder taskFragmentTransactionToken) {
+ if (mCurrentTransaction != null) {
+ mCurrentTransaction = null;
+ throw new IllegalStateException(
+ "The previous transaction has not been applied or aborted,");
+ }
+ mCurrentTransaction = new TransactionRecord(taskFragmentTransactionToken);
+ return mCurrentTransaction;
+ }
+
+ /**
+ * Gets the current {@link TransactionRecord} started from {@link #startNewTransaction}.
+ */
+ @NonNull
+ TransactionRecord getCurrentTransactionRecord() {
+ if (mCurrentTransaction == null) {
+ throw new IllegalStateException("startNewTransaction() is not invoked before calling"
+ + " getCurrentTransactionRecord().");
+ }
+ return mCurrentTransaction;
+ }
+
+ /** The current transaction. The manager should only handle one transaction at a time. */
+ class TransactionRecord {
+ /**
+ * {@link WindowContainerTransaction} containing the current change.
+ * @see #startNewTransaction(IBinder)
+ * @see #apply (boolean)
+ */
+ @NonNull
+ private final WindowContainerTransaction mTransaction = new WindowContainerTransaction();
+
+ /**
+ * If the current transaction is a response to a
+ * {@link android.window.TaskFragmentTransaction}, this is the
+ * {@link android.window.TaskFragmentTransaction#getTransactionToken()}.
+ * @see #startNewTransaction(IBinder)
+ */
+ @Nullable
+ private final IBinder mTaskFragmentTransactionToken;
+
+ /**
+ * To track of the origin type of the current {@link #mTransaction}. When
+ * {@link #apply (boolean)} to start a new transition, this is the type to request.
+ * @see #setOriginType(int)
+ * @see #getTransactionTransitionType()
+ */
+ @TransitionType
+ private int mOriginType = TRANSIT_NONE;
+
+ TransactionRecord(@Nullable IBinder taskFragmentTransactionToken) {
+ mTaskFragmentTransactionToken = taskFragmentTransactionToken;
+ }
+
+ @NonNull
+ WindowContainerTransaction getTransaction() {
+ ensureCurrentTransaction();
+ return mTransaction;
+ }
+
+ /**
+ * Sets the {@link TransitionType} that triggers this transaction. If there are multiple
+ * calls, only the first call will be respected as the "origin" type.
+ */
+ void setOriginType(@TransitionType int type) {
+ ensureCurrentTransaction();
+ if (mOriginType != TRANSIT_NONE) {
+ // Skip if the origin type has already been set.
+ return;
+ }
+ mOriginType = type;
+ }
+
+ /**
+ * Requests the system server to apply the current transaction started from
+ * {@link #startNewTransaction}.
+ * @param shouldApplyIndependently If {@code true}, the {@link #mCurrentTransaction} will
+ * request a new transition, which will be queued until the
+ * sync engine is free if there is any other active sync.
+ * If {@code false}, the {@link #startNewTransaction} will
+ * be directly applied to the active sync.
+ */
+ void apply(boolean shouldApplyIndependently) {
+ ensureCurrentTransaction();
+ if (mTaskFragmentTransactionToken != null) {
+ // If this is a response to a TaskFragmentTransaction.
+ mOrganizer.onTransactionHandled(mTaskFragmentTransactionToken, mTransaction,
+ getTransactionTransitionType(), shouldApplyIndependently);
+ } else {
+ mOrganizer.applyTransaction(mTransaction, getTransactionTransitionType(),
+ shouldApplyIndependently);
+ }
+ dispose();
+ }
+
+ /** Called when there is no need to {@link #apply(boolean)} the current transaction. */
+ void abort() {
+ ensureCurrentTransaction();
+ dispose();
+ }
+
+ private void dispose() {
+ TransactionManager.this.mCurrentTransaction = null;
+ }
+
+ private void ensureCurrentTransaction() {
+ if (TransactionManager.this.mCurrentTransaction != this) {
+ throw new IllegalStateException(
+ "This transaction has already been apply() or abort().");
+ }
+ }
+
+ /**
+ * Gets the {@link TransitionType} that we will request transition with for the
+ * current {@link WindowContainerTransaction}.
+ */
+ @VisibleForTesting
+ @TransitionType
+ int getTransactionTransitionType() {
+ // Use TRANSIT_CHANGE as default if there is not opening/closing window.
+ return mOriginType != TRANSIT_NONE ? mOriginType : TRANSIT_CHANGE;
+ }
+ }
+}
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 25d034756265..a40303150079 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
@@ -132,6 +132,7 @@ public class SplitControllerTest {
private SplitController mSplitController;
private SplitPresenter mSplitPresenter;
+ private TransactionManager mTransactionManager;
@Before
public void setUp() {
@@ -140,8 +141,10 @@ public class SplitControllerTest {
.getCurrentWindowLayoutInfo(anyInt(), any());
mSplitController = new SplitController(mWindowLayoutComponent);
mSplitPresenter = mSplitController.mPresenter;
+ mTransactionManager = mSplitController.mTransactionManager;
spyOn(mSplitController);
spyOn(mSplitPresenter);
+ spyOn(mTransactionManager);
doNothing().when(mSplitPresenter).applyTransaction(any(), anyInt(), anyBoolean());
final Configuration activityConfig = new Configuration();
activityConfig.windowConfiguration.setBounds(TASK_BOUNDS);
@@ -212,6 +215,8 @@ public class SplitControllerTest {
@Test
public void testOnTaskFragmentAppearEmptyTimeout() {
+ // Setup to make sure a transaction record is started.
+ mTransactionManager.startNewTransaction();
final TaskFragmentContainer tf = mSplitController.newContainer(mActivity, TASK_ID);
doCallRealMethod().when(mSplitController).onTaskFragmentAppearEmptyTimeout(any(), any());
mSplitController.onTaskFragmentAppearEmptyTimeout(mTransaction, tf);
@@ -615,6 +620,8 @@ public class SplitControllerTest {
@Test
public void testResolveActivityToContainer_placeholderRule_notInTaskFragment() {
+ // Setup to make sure a transaction record is started.
+ mTransactionManager.startNewTransaction();
setupPlaceholderRule(mActivity);
final SplitPlaceholderRule placeholderRule =
(SplitPlaceholderRule) mSplitController.getSplitRules().get(0);
@@ -647,6 +654,8 @@ public class SplitControllerTest {
@Test
public void testResolveActivityToContainer_placeholderRule_inTopMostTaskFragment() {
+ // Setup to make sure a transaction record is started.
+ mTransactionManager.startNewTransaction();
setupPlaceholderRule(mActivity);
final SplitPlaceholderRule placeholderRule =
(SplitPlaceholderRule) mSplitController.getSplitRules().get(0);
@@ -679,6 +688,8 @@ public class SplitControllerTest {
@Test
public void testResolveActivityToContainer_placeholderRule_inSecondarySplit() {
+ // Setup to make sure a transaction record is started.
+ mTransactionManager.startNewTransaction();
setupPlaceholderRule(mActivity);
final SplitPlaceholderRule placeholderRule =
(SplitPlaceholderRule) mSplitController.getSplitRules().get(0);
@@ -961,6 +972,8 @@ public class SplitControllerTest {
@Test
public void testGetPlaceholderOptions() {
+ // Setup to make sure a transaction record is started.
+ mTransactionManager.startNewTransaction();
doReturn(true).when(mActivity).isResumed();
assertNull(mSplitController.getPlaceholderOptions(mActivity, false /* isOnCreated */));
@@ -1147,8 +1160,6 @@ public class SplitControllerTest {
+ "of other properties",
SplitController.haveSamePresentation(splitRule1, splitRule2,
new WindowMetrics(TASK_BOUNDS, WindowInsets.CONSUMED)));
-
-
}
/** Creates a mock activity in the organizer process. */
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TransactionManagerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TransactionManagerTest.java
new file mode 100644
index 000000000000..62006bd51399
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TransactionManagerTest.java
@@ -0,0 +1,204 @@
+/*
+ * 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 android.view.WindowManager.TRANSIT_CHANGE;
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_OPEN;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.clearInvocations;
+
+import android.os.Binder;
+import android.os.IBinder;
+import android.platform.test.annotations.Presubmit;
+import android.window.TaskFragmentOrganizer;
+import android.window.WindowContainerTransaction;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.window.extensions.embedding.TransactionManager.TransactionRecord;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Test class for {@link TransactionManager}.
+ *
+ * Build/Install/Run:
+ * atest WMJetpackUnitTests:TransactionManagerTest
+ */
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TransactionManagerTest {
+
+ @Mock
+ private TaskFragmentOrganizer mOrganizer;
+ private TransactionManager mTransactionManager;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mTransactionManager = new TransactionManager(mOrganizer);
+ }
+
+ @Test
+ public void testStartNewTransaction() {
+ mTransactionManager.startNewTransaction();
+
+ // Throw exception if #startNewTransaction is called twice without #apply() or #abort().
+ assertThrows(IllegalStateException.class, mTransactionManager::startNewTransaction);
+
+ // Allow to start new after #apply() the last transaction.
+ TransactionRecord transactionRecord = mTransactionManager.startNewTransaction();
+ transactionRecord.apply(false /* shouldApplyIndependently */);
+ transactionRecord = mTransactionManager.startNewTransaction();
+
+ // Allow to start new after #abort() the last transaction.
+ transactionRecord.abort();
+ mTransactionManager.startNewTransaction();
+ }
+
+ @Test
+ public void testSetTransactionOriginType() {
+ // Return TRANSIT_CHANGE if there is no trigger type set.
+ TransactionRecord transactionRecord = mTransactionManager.startNewTransaction();
+
+ assertEquals(TRANSIT_CHANGE, transactionRecord.getTransactionTransitionType());
+
+ // Return the first set type.
+ mTransactionManager.getCurrentTransactionRecord().abort();
+ transactionRecord = mTransactionManager.startNewTransaction();
+ transactionRecord.setOriginType(TRANSIT_OPEN);
+
+ assertEquals(TRANSIT_OPEN, transactionRecord.getTransactionTransitionType());
+
+ transactionRecord.setOriginType(TRANSIT_CLOSE);
+
+ assertEquals(TRANSIT_OPEN, transactionRecord.getTransactionTransitionType());
+
+ // Reset when #startNewTransaction().
+ transactionRecord.abort();
+ transactionRecord = mTransactionManager.startNewTransaction();
+
+ assertEquals(TRANSIT_CHANGE, transactionRecord.getTransactionTransitionType());
+ }
+
+ @Test
+ public void testGetCurrentTransactionRecord() {
+ // Throw exception if #getTransaction is called without calling #startNewTransaction().
+ assertThrows(IllegalStateException.class, mTransactionManager::getCurrentTransactionRecord);
+
+ TransactionRecord transactionRecord = mTransactionManager.startNewTransaction();
+ assertNotNull(transactionRecord);
+
+ // Same WindowContainerTransaction should be returned.
+ assertSame(transactionRecord, mTransactionManager.getCurrentTransactionRecord());
+
+ // Reset after #abort().
+ transactionRecord.abort();
+ assertThrows(IllegalStateException.class, mTransactionManager::getCurrentTransactionRecord);
+
+ // New WindowContainerTransaction after #startNewTransaction().
+ mTransactionManager.startNewTransaction();
+ assertNotEquals(transactionRecord, mTransactionManager.getCurrentTransactionRecord());
+
+ // Reset after #apply().
+ mTransactionManager.getCurrentTransactionRecord().apply(
+ false /* shouldApplyIndependently */);
+ assertThrows(IllegalStateException.class, mTransactionManager::getCurrentTransactionRecord);
+ }
+
+ @Test
+ public void testApply() {
+ // #applyTransaction(false)
+ TransactionRecord transactionRecord = mTransactionManager.startNewTransaction();
+ int transitionType = transactionRecord.getTransactionTransitionType();
+ WindowContainerTransaction wct = transactionRecord.getTransaction();
+ transactionRecord.apply(false /* shouldApplyIndependently */);
+
+ verify(mOrganizer).applyTransaction(wct, transitionType,
+ false /* shouldApplyIndependently */);
+
+ // #applyTransaction(true)
+ clearInvocations(mOrganizer);
+ transactionRecord = mTransactionManager.startNewTransaction();
+ transitionType = transactionRecord.getTransactionTransitionType();
+ wct = transactionRecord.getTransaction();
+ transactionRecord.apply(true /* shouldApplyIndependently */);
+
+ verify(mOrganizer).applyTransaction(wct, transitionType,
+ true /* shouldApplyIndependently */);
+
+ // #onTransactionHandled(false)
+ clearInvocations(mOrganizer);
+ IBinder token = new Binder();
+ transactionRecord = mTransactionManager.startNewTransaction(token);
+ transitionType = transactionRecord.getTransactionTransitionType();
+ wct = transactionRecord.getTransaction();
+ transactionRecord.apply(false /* shouldApplyIndependently */);
+
+ verify(mOrganizer).onTransactionHandled(token, wct, transitionType,
+ false /* shouldApplyIndependently */);
+
+ // #onTransactionHandled(true)
+ clearInvocations(mOrganizer);
+ token = new Binder();
+ transactionRecord = mTransactionManager.startNewTransaction(token);
+ transitionType = transactionRecord.getTransactionTransitionType();
+ wct = transactionRecord.getTransaction();
+ transactionRecord.apply(true /* shouldApplyIndependently */);
+
+ verify(mOrganizer).onTransactionHandled(token, wct, transitionType,
+ true /* shouldApplyIndependently */);
+
+ // Throw exception if there is any more interaction.
+ final TransactionRecord record = transactionRecord;
+ assertThrows(IllegalStateException.class,
+ () -> record.apply(false /* shouldApplyIndependently */));
+ assertThrows(IllegalStateException.class,
+ () -> record.apply(true /* shouldApplyIndependently */));
+ assertThrows(IllegalStateException.class,
+ record::abort);
+ }
+
+ @Test
+ public void testAbort() {
+ final TransactionRecord transactionRecord = mTransactionManager.startNewTransaction();
+ transactionRecord.abort();
+
+ // Throw exception if there is any more interaction.
+ verifyNoMoreInteractions(mOrganizer);
+ assertThrows(IllegalStateException.class,
+ () -> transactionRecord.apply(false /* shouldApplyIndependently */));
+ assertThrows(IllegalStateException.class,
+ () -> transactionRecord.apply(true /* shouldApplyIndependently */));
+ assertThrows(IllegalStateException.class,
+ transactionRecord::abort);
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasks.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasks.aidl
index b71cc32a0347..1a6c1d65db03 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasks.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasks.aidl
@@ -16,7 +16,7 @@
package com.android.wm.shell.recents;
-import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
import com.android.wm.shell.recents.IRecentTasksListener;
import com.android.wm.shell.util.GroupedRecentTaskInfo;
@@ -44,5 +44,5 @@ interface IRecentTasks {
/**
* Gets the set of running tasks.
*/
- ActivityManager.RunningTaskInfo[] getRunningTasks(int maxNum) = 4;
+ RunningTaskInfo[] getRunningTasks(int maxNum) = 4;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasksListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasksListener.aidl
index 59f72335678e..e8f58fe2bfad 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasksListener.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasksListener.aidl
@@ -16,7 +16,7 @@
package com.android.wm.shell.recents;
-import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
/**
* Listener interface that Launcher attaches to SystemUI to get split-screen callbacks.
@@ -31,10 +31,10 @@ oneway interface IRecentTasksListener {
/**
* Called when a running task appears.
*/
- void onRunningTaskAppeared(in ActivityManager.RunningTaskInfo taskInfo);
+ void onRunningTaskAppeared(in RunningTaskInfo taskInfo);
/**
* Called when a running task vanishes.
*/
- void onRunningTaskVanished(in ActivityManager.RunningTaskInfo taskInfo);
-} \ No newline at end of file
+ void onRunningTaskVanished(in RunningTaskInfo taskInfo);
+}
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 9102bd3a9b6a..e2ac01f7b003 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
@@ -207,6 +207,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private int mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
private DefaultMixedHandler mMixedHandler;
+ private final Toast mSplitUnsupportedToast;
private final SplitWindowManager.ParentContainerCallbacks mParentContainerCallbacks =
new SplitWindowManager.ParentContainerCallbacks() {
@@ -300,6 +301,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mDisplayLayout = new DisplayLayout(displayController.getDisplayLayout(displayId));
transitions.addHandler(this);
mTaskOrganizer.addFocusListener(this);
+ mSplitUnsupportedToast = Toast.makeText(mContext,
+ R.string.dock_non_resizeble_failed_to_dock_text, Toast.LENGTH_SHORT);
}
@VisibleForTesting
@@ -329,6 +332,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mDisplayController.addDisplayWindowListener(this);
mDisplayLayout = new DisplayLayout();
transitions.addHandler(this);
+ mSplitUnsupportedToast = Toast.makeText(mContext,
+ R.string.dock_non_resizeble_failed_to_dock_text, Toast.LENGTH_SHORT);
}
public void setMixedHandler(DefaultMixedHandler mixedHandler) {
@@ -470,6 +475,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mMainExecutor.execute(() ->
exitSplitScreen(mMainStage.getChildCount() == 0
? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
+ mSplitUnsupportedToast.show();
} else {
// Switch the split position if launching as MULTIPLE_TASK failed.
if ((fillInIntent.getFlags() & FLAG_ACTIVITY_MULTIPLE_TASK) != 0) {
@@ -736,6 +742,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mMainExecutor.execute(() ->
exitSplitScreen(mMainStage.getChildCount() == 0
? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
+ mSplitUnsupportedToast.show();
} else {
mSyncQueue.queue(evictWct);
}
@@ -2287,13 +2294,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Override
public void onNoLongerSupportMultiWindow() {
if (mMainStage.isActive()) {
- final Toast splitUnsupportedToast = Toast.makeText(mContext,
- R.string.dock_non_resizeble_failed_to_dock_text, Toast.LENGTH_SHORT);
final boolean isMainStage = mMainStageListener == this;
if (!ENABLE_SHELL_TRANSITIONS) {
StageCoordinator.this.exitSplitScreen(isMainStage ? mMainStage : mSideStage,
EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW);
- splitUnsupportedToast.show();
+ mSplitUnsupportedToast.show();
return;
}
@@ -2302,7 +2307,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
prepareExitSplitScreen(stageType, wct);
mSplitTransitions.startDismissTransition(wct,StageCoordinator.this, stageType,
EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW);
- splitUnsupportedToast.show();
+ mSplitUnsupportedToast.show();
}
}
diff --git a/packages/SoundPicker/res/values-am/strings.xml b/packages/SoundPicker/res/values-am/strings.xml
index 07aee8a646ec..85206c0b46a0 100644
--- a/packages/SoundPicker/res/values-am/strings.xml
+++ b/packages/SoundPicker/res/values-am/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="ringtone_default" msgid="798836092118824500">"ነባሪ የስልክ ላይ ጥሪ"</string>
- <string name="notification_sound_default" msgid="8133121186242636840">"ነባሪ የማሳወቂያ ድምጽ"</string>
+ <string name="notification_sound_default" msgid="8133121186242636840">"ነባሪ የማሳወቂያ ድምፅ"</string>
<string name="alarm_sound_default" msgid="4787646764557462649">"ነባሪ የማንቂያ ድምፅ"</string>
<string name="add_ringtone_text" msgid="6642389991738337529">"የጥሪ ቅላጼ አክል"</string>
<string name="add_alarm_text" msgid="3545497316166999225">"የማንቂያ ደውል አክል"</string>
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
index 23cee4d0972d..ca36fa43da76 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -865,7 +865,7 @@ private class AnimatedDialog(
return
}
- ViewRootSync.synchronizeNextDraw(decorView, controller.viewRoot.view, then)
+ ViewRootSync.synchronizeNextDraw(controller.viewRoot.view, decorView, then)
decorView.invalidate()
controller.viewRoot.view.invalidate()
}
diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt
index 491ec20c519d..a850238eb52f 100644
--- a/packages/SystemUI/ktfmt_includes.txt
+++ b/packages/SystemUI/ktfmt_includes.txt
@@ -246,8 +246,6 @@
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLogger.kt
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
--packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt
--packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipRootView.kt
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLogger.kt
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLogger.kt
-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
@@ -528,6 +526,8 @@
-packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt
-packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt
-packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
+-packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarRootView.kt
-packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt
-packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt
-packages/SystemUI/src/com/android/systemui/tv/TVSystemUICoreStartableModule.kt
@@ -678,7 +678,6 @@
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
--packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculatorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitorTest.kt
@@ -833,6 +832,7 @@
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/WalletControllerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateLoggingProviderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt
diff --git a/packages/SystemUI/res-keyguard/values-as/strings.xml b/packages/SystemUI/res-keyguard/values-as/strings.xml
index b22655af4c74..cbfb325fa9b3 100644
--- a/packages/SystemUI/res-keyguard/values-as/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-as/strings.xml
@@ -64,9 +64,9 @@
<string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"ছিম কার্ড আনলক কৰি থকা হৈছে…"</string>
<string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"৪টাৰ পৰা ৮টা সংখ্যাযুক্ত এটা পিন লিখক।"</string>
<string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK ক\'ডটো ৮টা বা তাতকৈ অধিক সংখ্যা থকা হ\'ব লাগিব।"</string>
- <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"আপুনি আপোনাৰ পিন <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ লিখিছে। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g>ছেকেণ্ডৰ পিছত আকৌ চেষ্টা কৰক।"</string>
+ <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"আপুনি আপোনাৰ পিন <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ লিখিছে। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g>ছেকেণ্ডৰ পাছত আকৌ চেষ্টা কৰক।"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"আপুনি আপোনাৰ পাছৱৰ্ড <xliff:g id="NUMBER_0">%1$d</xliff:g>বাৰ ভুলকৈ লিখিছে। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ছেকেণ্ডৰ পাছত আকৌ চেষ্টা কৰক।"</string>
- <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"আপুনি আপোনাৰ আনলক আৰ্হি <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আঁকিছে। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g>ছেকেণ্ডৰ পিছত আকৌ চেষ্টা কৰক।"</string>
+ <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"আপুনি আপোনাৰ আনলক আৰ্হি <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আঁকিছে। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g>ছেকেণ্ডৰ পাছত আকৌ চেষ্টা কৰক।"</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"ছিমৰ ভুল পিন ক\'ড, আপোনাৰ ডিভাইচটো আনলক কৰিবলৈ আপুনি এতিয়া আপোনাৰ বাহকৰ সৈতে যোগাযোগ কৰিবই লাগিব।"</string>
<string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{ছিমৰ পিন ক’ড ভুল হৈছে, আপোনাৰ ডিভাইচ আনলক কৰিবলৈ আপোনাৰ বাহকৰ লগত যোগাযোগ কৰিবই লগা হোৱাৰ পূৰ্বে আপোনাৰ ওচৰত # টা প্ৰয়াস বাকী আছে।}one{ছিমৰ পিন ক’ড ভুল হৈছে, আপোনাৰ ওচৰত # টা প্ৰয়াস বাকী আছে। }other{ছিমৰ পিন ক’ড ভুল হৈছে, আপোনাৰ ওচৰত # টা প্ৰয়াস বাকী আছে। }}"</string>
<string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"ছিম ব্যৱহাৰযোগ্য নহয়। আপোনাৰ বাহকৰ সৈতে যোগাযোগ কৰক।"</string>
@@ -75,9 +75,9 @@
<string name="kg_password_puk_failed" msgid="6778867411556937118">"ছিম PUKৰ জৰিয়তে আনলক কৰিব পৰা নগ\'ল!"</string>
<string name="accessibility_ime_switch_button" msgid="9082358310194861329">"ইনপুট পদ্ধতি সলনি কৰক"</string>
<string name="airplane_mode" msgid="2528005343938497866">"এয়াৰপ্লে’ন ম’ড"</string>
- <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ডিভাইচ ৰিষ্টাৰ্ট হোৱাৰ পিছত আৰ্হি দিয়াটো বাধ্যতামূলক"</string>
- <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"ডিভাইচ ৰিষ্টাৰ্ট হোৱাৰ পিছত পিন দিয়াটো বাধ্যতামূলক"</string>
- <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"ডিভাইচ ৰিষ্টাৰ্ট হোৱাৰ পিছত পাছৱৰ্ড দিয়াটো বাধ্যতামূলক"</string>
+ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ডিভাইচ ৰিষ্টাৰ্ট হোৱাৰ পাছত আৰ্হি দিয়াটো বাধ্যতামূলক"</string>
+ <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"ডিভাইচ ৰিষ্টাৰ্ট হোৱাৰ পাছত পিন দিয়াটো বাধ্যতামূলক"</string>
+ <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"ডিভাইচ ৰিষ্টাৰ্ট হোৱাৰ পাছত পাছৱৰ্ড দিয়াটো বাধ্যতামূলক"</string>
<string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"অতিৰিক্ত সুৰক্ষাৰ বাবে আর্হি দিয়াটো বাধ্যতামূলক"</string>
<string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"অতিৰিক্ত সুৰক্ষাৰ বাবে পিন দিয়াটো বাধ্যতামূলক"</string>
<string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"অতিৰিক্ত সুৰক্ষাৰ বাবে পাছৱর্ড দিয়াটো বাধ্যতামূলক"</string>
diff --git a/packages/SystemUI/res/layout/media_ttt_chip.xml b/packages/SystemUI/res/layout/chipbar.xml
index ae8e38e2634b..4da77118f00b 100644
--- a/packages/SystemUI/res/layout/media_ttt_chip.xml
+++ b/packages/SystemUI/res/layout/chipbar.xml
@@ -16,7 +16,7 @@
<!-- Wrap in a frame layout so that we can update the margins on the inner layout. (Since this view
is the root view of a window, we cannot change the root view's margins.) -->
<!-- Alphas start as 0 because the view will be animated in. -->
-<com.android.systemui.media.taptotransfer.sender.MediaTttChipRootView
+<com.android.systemui.temporarydisplay.chipbar.ChipbarRootView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/media_ttt_sender_chip"
@@ -97,4 +97,4 @@
/>
</LinearLayout>
-</com.android.systemui.media.taptotransfer.sender.MediaTttChipRootView>
+</com.android.systemui.temporarydisplay.chipbar.ChipbarRootView>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index f07f10d47476..eccce2f79844 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -94,19 +94,14 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ለአንድ የማያ ገጽ ቀረጻ ክፍለ-ጊዜ በመካሄድ ያለ ማሳወቂያ"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"መቅረጽ ይጀመር?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"እየቀረጹ ሳለ የAndroid ስርዓት በማያ ገጽዎ ላይ የሚታይ ወይም በመሣሪያዎ ላይ የሚጫወት ማንኛውም ሚስጥራዊነት ያለው መረጃን መያዝ ይችላል። ይህ የይለፍ ቃላትን፣ የክፍያ መረጃን፣ ፎቶዎችን፣ መልዕክቶችን እና ኦዲዮን ያካትታል።"</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"መላው ማያ ገጹን ቅረጽ"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"አንድ ነጠላ መተግበሪያን ቅረጽ"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"እየቀረጹ እያለ Android በማያ ገጽዎ ላይ ለሚታይ ወይም በመሣሪያዎ ላይ ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ በይለፍ ቃላት፣ በክፍያ ዝርዝሮች፣ በመልዕክቶች ወይም በሌሎች ልዩ ጥንቃቄ የሚያስፈልጋቸው መረጃዎች ላይ ጥንቃቄ ያድርጉ።"</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"አንድን መተግበሪያ እየቀረጹ ሳለ Android በዚያ መተግበሪያ ላይ ለሚታይ ወይም ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ በይለፍ ቃላት፣ በክፍያ ዝርዝሮች፣ በመልዕክቶች ወይም በሌሎች ልዩ ጥንቃቄ የሚያስፈልጋቸው መረጃዎች ላይ ጥንቃቄ ያድርጉ።"</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"መቅረጽ ጀምር"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"ኦዲዮን ቅረጽ"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"የመሣሪያ ኦዲዮ"</string>
- <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"እንደ ሙዚቃ፣ ጥሪዎች እና የጥሪ ቅላጼዎች ያሉ የመሣሪያዎ ድምጽ"</string>
+ <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"እንደ ሙዚቃ፣ ጥሪዎች እና የጥሪ ቅላጼዎች ያሉ የመሣሪያዎ ድምፅ"</string>
<string name="screenrecord_mic_label" msgid="2111264835791332350">"ማይክሮፎን"</string>
<string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"የመሣሪያ ኦዲዮ እና ማይክሮፎን"</string>
<string name="screenrecord_start" msgid="330991441575775004">"ጀምር"</string>
@@ -274,14 +269,14 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"የ<xliff:g id="DATA_LIMIT">%s</xliff:g> ማስጠንቀቂያ"</string>
<string name="quick_settings_work_mode_label" msgid="6440531507319809121">"የሥራ መተግበሪያዎች"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"የምሽት ብርሃን"</string>
- <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"ጸሐይ ስትጠልቅ ይበራል"</string>
- <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"ጸሐይ እስክትወጣ ድረስ"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"ፀሐይ ስትጠልቅ ይበራል"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"ፀሐይ እስክትወጣ ድረስ"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> ላይ ይበራል"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"እስከ <xliff:g id="TIME">%s</xliff:g> ድረስ"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ጨለማ ገጽታ"</string>
<string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ባትሪ ቆጣቢ"</string>
- <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ጸሐይ ስትጠልቅ ይበራል"</string>
- <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ጸሐይ እስክትወጣ ድረስ"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ፀሐይ ስትጠልቅ ይበራል"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ፀሐይ እስክትወጣ ድረስ"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> ላይ ይበራል"</string>
<string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"እስከ <xliff:g id="TIME">%s</xliff:g> ድረስ"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at_bedtime" msgid="2274300599408864897">"በመኝታ ሰዓት ላይ"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"ይህን ተግባር የሚያቀርበው አገልግሎት በእርስዎ ማያ ገጽ ላይ ያለን ወይም በእርስዎ መሣሪያ ላይ በመጫወት ላይ ያለን ሁሉንም መረጃ በቀረጻ ወይም casting ላይ እያለ መዳረሻ ይኖረዋል። ይህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ ፎቶዎች፣ መልዕክቶች እና እርስዎ የሚጫውቱት ኦዲዮን የመሳሰለ መረጃን ያካትታል።"</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"ቀረጻ ወይም cast ማድረግ ይጀምር?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"ከ<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ጋር ቀረጻ ወይም casting ይጀምር?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> እንዲያጋራ ወይም እንዲቀርጽ ይፈቀድለት?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"መላው ማያ ገጽ"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"አንድ ነጠላ መተግበሪያ"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"ሲያጋሩ፣ ሲቀርጹ ወይም cast ሲያደርጉ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> በማያ ገጽዎ ላይ ለሚታይ ወይም በመሣሪያዎ ላይ ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ በይለፍ ቃላት፣ በክፍያ ዝርዝሮች፣ በመልዕክቶች ወይም በሌሎች ልዩ ጥንቃቄ የሚያስፈልጋቸው መረጃዎች ላይ ጥንቃቄ ያድርጉ።"</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"አንድን መተግበሪያ ሲያጋሩ፣ ሲቀርጹ ወይም cast ሲያደርጉ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> በዚያ መተግበሪያ ላይ ለሚታይ ወይም ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ በይለፍ ቃላት፣ በክፍያ ዝርዝሮች፣ በመልዕክቶች ወይም በሌሎች ልዩ ጥንቃቄ የሚያስፈልጋቸው መረጃዎች ላይ ጥንቃቄ ያድርጉ።"</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"ቀጥል"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"መተግበሪያ ያጋሩ ወይም ይቅረጹ"</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>
@@ -445,7 +433,7 @@
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"የሥዕል መግለጫ ጽሑፎች ንብርብር"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"አንቃ"</string>
<string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"አሰናክል"</string>
- <string name="sound_settings" msgid="8874581353127418308">"ድምጽ እና ንዝረት"</string>
+ <string name="sound_settings" msgid="8874581353127418308">"ድምፅ እና ንዝረት"</string>
<string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ቅንብሮች"</string>
<string name="screen_pinning_title" msgid="9058007390337841305">"መተግበሪያ ተሰክቷል"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"ይሄ እስኪነቅሉት ድረስ በእይታ ውስጥ ያስቀምጠዋል። ለመንቀል ተመለስ እና አጠቃላይ ዕይታ የሚለውን ይጫኑ እና ይያዙ።"</string>
@@ -527,11 +515,11 @@
<string name="notification_silence_title" msgid="8608090968400832335">"ፀጥ ያለ"</string>
<string name="notification_alert_title" msgid="3656229781017543655">"ነባሪ"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"ራስ-ሰር"</string>
- <string name="notification_channel_summary_low" msgid="4860617986908931158">"ምንም ድምጽ ወይም ንዝረት የለም"</string>
- <string name="notification_conversation_summary_low" msgid="1734433426085468009">"ምንም ድምጽ ወይም ንዝረት የለም እና በውይይት ክፍል ላይ አይታይም"</string>
+ <string name="notification_channel_summary_low" msgid="4860617986908931158">"ምንም ድምፅ ወይም ንዝረት የለም"</string>
+ <string name="notification_conversation_summary_low" msgid="1734433426085468009">"ምንም ድምፅ ወይም ንዝረት የለም እና በውይይት ክፍል ላይ አይታይም"</string>
<string name="notification_channel_summary_default" msgid="3282930979307248890">"በእርስዎ የስልክ ቅንብሮች የሚወሰን ሆኖ ሊደውል ወይም ሊነዝር ይችላል"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"በእርስዎ የስልክ ቅንብሮች የሚወሰን ሆኖ ሊደውል ወይም ሊነዝር ይችላል። የ<xliff:g id="APP_NAME">%1$s</xliff:g> አረፋ ውይይቶች በነባሪነት።"</string>
- <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ይህ ማሳወቂያ ድምጽ ወይም ንዝረት መደረግ ካለበት ስርዓቱ እንዲወሰን ያድርጉት"</string>
+ <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ይህ ማሳወቂያ ድምፅ ወይም ንዝረት መደረግ ካለበት ስርዓቱ እንዲወሰን ያድርጉት"</string>
<string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"&lt;b&gt;ሁኔታ:&lt;/b&gt; ለነባሪ ከፍ ተዋውቋል።"</string>
<string name="notification_channel_summary_automatic_silenced" msgid="7403004439649872047">"&lt;b&gt;ሁኔታ:&lt;/b&gt; ወደ ዝምታ ዝቅ ተደርጓል"</string>
<string name="notification_channel_summary_automatic_promoted" msgid="1301710305149590426">"&lt;b&gt;ሁኔታ:&lt;/b&gt; ክፍተኛ ደረጃ ተሰጥቶታል"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 732c2e62c29f..8f996fb9794a 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"إشعار مستمر لجلسة تسجيل شاشة"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"هل تريد بدء التسجيل؟"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"‏أثناء التسجيل، يمكن أن يسجّل نظام Android أي معلومات حساسة مرئية على شاشتك أو يتم تشغيلها على جهازك. ويشمل ذلك كلمات المرور ومعلومات الدفع والصور والرسائل والمقاطع الصوتية."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"تسجيل الشاشة بالكامل"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"تسجيل محتوى تطبيق واحد"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"‏أثناء التسجيل، يمكن لنظام Android الوصول إلى كل العناصر المرئية على شاشتك أو التي يتم تشغيلها على جهازك، لذا يُرجى توخي الحذر بشأن كلمات المرور أو تفاصيل الدفع أو الرسائل أو المعلومات الحساسة الأخرى."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"‏أثناء تسجيل محتوى أحد التطبيقات، يمكن لنظام Android الوصول إلى كل العناصر المعروضة أو التي يتم تشغيلها في ذلك التطبيق، لذا يُرجى توخي الحذر بشأن كلمات المرور أو تفاصيل الدفع أو الرسائل أو المعلومات الحساسة الأخرى."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"بدء التسجيل"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"تسجيل الصوت"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"صوت الجهاز"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"الصوت من جهازك، مثلاً الموسيقى والمكالمات ونغمات الرنين"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"هل تريد السماح لتطبيق <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>بالمشاركة أو التسجيل؟"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"الشاشة بالكامل"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"تطبيق واحد"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"أثناء المشاركة أو التسجيل أو البث، يمكن لتطبيق <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> الوصول إلى كل العناصر المرئية على شاشتك أو التي يتم تشغيلها على جهازك، لذا يُرجى توخي الحذر بشأن كلمات المرور أو تفاصيل الدفع أو الرسائل أو المعلومات الحساسة الأخرى."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"أثناء مشاركة محتوى تطبيق أو تسجيله أو بثه، يمكن لتطبيق <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> الوصول إلى كل العناصر المعروضة أو التي يتم تشغيلها في ذلك التطبيق، لذا يُرجى توخي الحذر بشأن كلمات المرور أو تفاصيل الدفع أو الرسائل أو المعلومات الحساسة الأخرى."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"متابعة"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"مشاركة محتوى تطبيق أو تسجيله"</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>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index c2f8e4350df6..fe95fa024b93 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রীন ৰেকৰ্ডিং ছেশ্বন চলি থকা সময়ত পোৱা জাননী"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"ৰেকৰ্ড কৰা আৰম্ভ কৰিবনে?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"ৰেকৰ্ড কৰি থাকোঁতে, Android Systemএ আপোনাৰ স্ক্রীনত দৃশ্যমান হোৱা অথবা আপোনাৰ ডিভাইচত প্লে’ হৈ থকা যিকোনো সংবেনদশীল তথ্য কেপচাৰ কৰিব পাৰে। এইটোত পাছৱর্ড, পৰিশোধৰ তথ্য, ফট’, বার্তাসমূহ আৰু অডিঅ’ অন্তর্ভুক্ত হয়।"</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"গোটেই স্ক্ৰীনখন ৰেকৰ্ড কৰক"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"এটা এপ্ ৰেকৰ্ড কৰক"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"আপুনি ৰেকৰ্ড কৰাৰ সময়ত, আপোনাৰ স্ক্ৰীনখনত দৃশ্যমান যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ Androidৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা অথবা অন্য সংবেদনশীল তথ্যৰ ক্ষেত্ৰত সাৱধান হওক।"</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"আপুনি এপ এপ্ ৰেকৰ্ড কৰাৰ সময়ত সেইটো এপত দৃশ্যমান যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ Androidৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা অথবা অন্য সংবেদনশীল তথ্যৰ ক্ষেত্ৰত সাৱধান হওক।"</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"ৰেকৰ্ডিং আৰম্ভ কৰক"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"অডিঅ’ ৰেকৰ্ড কৰক"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"ডিভাইচৰ অডিঅ’"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"সংগীত, কল আৰু ৰিংট’নসমূহৰ দৰে আপোনাৰ ডিভাইচৰ পৰা কেপচাৰ কৰিব পৰা ধ্বনি"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ক শ্বেয়াৰ অথবা ৰেকৰ্ড কৰিবলৈ অনুমতি দিবনে?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"সম্পূৰ্ণ স্ক্ৰীন"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"এটা একক এপ্"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"আপুনি শ্বেয়াৰ কৰা, ৰেকৰ্ড কৰা অথবা কাষ্ট কৰাৰ সময়ত, আপোনাৰ স্ক্ৰীনখনত দৃশ্যমান যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা অথবা অন্য সংবেদনশীল তথ্যৰ ক্ষেত্ৰত সাৱধান হওক।"</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"আপুনি শ্বেয়াৰ কৰা, ৰেকৰ্ড কৰা অথবা কাষ্ট কৰাৰ সময়ত, সেইটো এপত দৃশ্যমান যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা অথবা অন্য সংবেদনশীল তথ্যৰ ক্ষেত্ৰত সাৱধান হওক।"</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"অব্যাহত ৰাখক"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"এটা এপ্ শ্বেয়াৰ অথবা ৰেকৰ্ড কৰক"</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>
@@ -575,7 +563,7 @@
<string name="keyboard_key_dpad_down" msgid="2110172278574325796">"তললৈ"</string>
<string name="keyboard_key_dpad_left" msgid="8329738048908755640">"বাওঁফালে"</string>
<string name="keyboard_key_dpad_right" msgid="6282105433822321767">"সোঁফালে"</string>
- <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"স্ক্ৰীণৰ মাজত"</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_enter" msgid="8633362970109751646">"এণ্টাৰ"</string>
@@ -596,7 +584,7 @@
<string name="keyboard_key_numpad_template" msgid="7316338238459991821">"নামপেড <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="notif_inline_reply_remove_attachment_description" msgid="7954075334095405429">"সংলগ্নক আঁতৰাওক"</string>
<string name="keyboard_shortcut_group_system" msgid="1583416273777875970">"ছিষ্টেম"</string>
- <string name="keyboard_shortcut_group_system_home" msgid="7465138628692109907">"গৃহ স্ক্ৰীণ"</string>
+ <string name="keyboard_shortcut_group_system_home" msgid="7465138628692109907">"গৃহ স্ক্ৰীন"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="8628108256824616927">"শেহতীয়াসমূহ"</string>
<string name="keyboard_shortcut_group_system_back" msgid="1055709713218453863">"উভতি যাওক"</string>
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"জাননীসমূহ"</string>
@@ -693,7 +681,7 @@
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"যত্ন লোৱাৰ পদক্ষেপসমূহ চাওক"</string>
<string name="high_temp_title" msgid="2218333576838496100">"ফ\'নটো গৰম হ\'বলৈ ধৰিছে"</string>
<string name="high_temp_notif_message" msgid="1277346543068257549">"ফ’নটো ঠাণ্ডা হৈ থকাৰ সময়ত কিছুমান সুবিধা উপলব্ধ নহয়।\nঅধিক তথ্যৰ বাবে টিপক"</string>
- <string name="high_temp_dialog_message" msgid="3793606072661253968">"আপোনাৰ ফ\'নটোৱে নিজে নিজে ঠাণ্ডা হ\'বলৈ স্বয়ংক্ৰিয়ভাৱে চেষ্টা কৰিব। আপুনি ফ\'নটো ব্যৱহাৰ কৰি থাকিব পাৰে কিন্তু ই লাহে লাহে চলিব পাৰে।\n\nফ\'নটো সম্পূৰ্ণভাৱে ঠাণ্ডা হোৱাৰ পিছত ই আগৰ নিচিনাকৈয়েই চলিব।"</string>
+ <string name="high_temp_dialog_message" msgid="3793606072661253968">"আপোনাৰ ফ\'নটোৱে নিজে নিজে ঠাণ্ডা হ\'বলৈ স্বয়ংক্ৰিয়ভাৱে চেষ্টা কৰিব। আপুনি ফ\'নটো ব্যৱহাৰ কৰি থাকিব পাৰে কিন্তু ই লাহে লাহে চলিব পাৰে।\n\nফ\'নটো সম্পূৰ্ণভাৱে ঠাণ্ডা হোৱাৰ পাছত ই আগৰ নিচিনাকৈয়েই চলিব।"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"যত্ন লোৱাৰ পদক্ষেপসমূহ চাওক"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"আপোনাৰ ডিভাইচটো আনপ্লাগ কৰক"</string>
<string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"আপোনাৰ ডিভাইচটো চাৰ্জিং প’ৰ্টৰ ওচৰত গৰম হৈছে। যদি এইটো কোনো চার্জাৰ অথবা ইউএছবিৰ সহায়ক সামগ্ৰীৰ সৈতে সংযুক্ত হৈ আছে, ইয়াক আনপ্লাগ কৰক আৰু কে’বলডালো গৰম হ\'ব পাৰে, গতিকে যত্ন লওক।"</string>
@@ -722,7 +710,7 @@
<string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string>
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> চলি আছে"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"এপ্‌টো ইনষ্ট\'ল নকৰাকৈ খোলা হৈছে।"</string>
- <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ইনষ্ট\'ল নকৰাকৈয়েই এপটো খোলা হৈছে। অধিক জানিবলৈ টিপক।"</string>
+ <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ইনষ্ট\'ল নকৰাকৈয়েই এপ্‌টো খোলা হৈছে। অধিক জানিবলৈ টিপক।"</string>
<string name="app_info" msgid="5153758994129963243">"এপৰ তথ্য"</string>
<string name="go_to_web" msgid="636673528981366511">"ব্ৰাউজাৰলৈ যাওক"</string>
<string name="mobile_data" msgid="4564407557775397216">"ম’বাইল ডেটা"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index fa6da9413356..cbc7c8aea155 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущо известие за сесия за записване на екрана"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Да се стартира ли записът?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"По време на записване системата Android може да запише и поверителна информация, която е показана на екрана или възпроизвеждана на устройството ви. Това включва пароли, данни за плащане, снимки, съобщения и аудио."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Записване на целия екран"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Записване на едно приложение"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Когато записвате, Android има достъп до всичко, което се вижда на екрана ви или се възпроизвежда на устройството ви, затова бъдете внимателни с пароли, подробности за начини на плащане, съобщения или друга поверителна информация."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Когато записвате приложение, Android има достъп до всичко, което се показва или възпроизвежда в това приложение, затова бъдете внимателни с пароли, подробности за начини на плащане, съобщения или друга поверителна информация."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Стартиране на записа"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Записване на звук"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Аудио от устройството"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Звук от устройството ви, като например музика, обаждания и мелодии"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Разрешавате ли на <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> да споделя и записва?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Цял екран"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Едно приложение"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Когато споделяте, записвате или предавате, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има достъп до всичко, което се вижда на екрана ви или се възпроизвежда на устройството ви, затова бъдете внимателни с пароли, подробности за начини на плащане, съобщения или друга поверителна информация."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Когато споделяте, записвате или предавате, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има достъп до всичко, което се показва или възпроизвежда в това приложение, затова бъдете внимателни с пароли, подробности за начини на плащане, съобщения или друга поверителна информация."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Напред"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Споделяне или записване на приложение"</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>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 8dc5f33b8358..44fb0e610ef7 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রিন রেকর্ডিং সেশন চলার বিজ্ঞপ্তি"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"রেকর্ডিং শুরু করবেন?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"রেকর্ড করার সময়, আপনার স্ক্রিনে দেখানো বা ডিভাইসে চালানো যেকোনও ধরনের সংবেদনশীল তথ্য Android সিস্টেম ক্যাপচার করতে পারে। এর মধ্যে পাসওয়ার্ড, পেমেন্টের তথ্য, ফটো, মেসেজ এবং অডিও সম্পর্কিত তথ্য থাকে।"</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"সম্পূর্ণ স্ক্রিন রেকর্ড করুন"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"একটিমাত্র অ্যাপ রেকর্ড করুন"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"আপনার রেকর্ড করার সময়, স্ক্রিনে দেখা যায় বা ডিভাইসে খেলা হয় এমন সব কিছু অ্যাক্সেস করার অনুমতি Android-এর আছে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ বা অন্য সংবেদনশীল তথ্য সম্পর্কে সতর্ক থাকুন।"</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"কোনও অ্যাপ আপনার রেকর্ড করার সময়, সেই অ্যাপে দেখা যায় বা খেলা হয় এমন সব কিছু অ্যাক্সেস করার অনুমতি Android-এর আছে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ বা অন্য সংবেদনশীল তথ্য সম্পর্কে সতর্ক থাকুন।"</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"রেকর্ড করা শুরু করুন"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"অডিও রেকর্ড করুন"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"ডিভাইস অডিও"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"মিউজিক, কল এবং রিংটোনগুলির মতো আপনার ডিভাইস থেকে সাউন্ড"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-কে শেয়ার বা রেকর্ড করার অনুমতি দেবেন?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"সম্পূর্ণ স্ক্রিন"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"একটি মাত্র অ্যাপ"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"আপনার শেয়ার করা, রেকর্ড করা বা কাস্ট করার সময়, স্ক্রিনে দেখা যায় বা ডিভাইসে খেলা হয় এমন সব কিছু অ্যাক্সেস করার অনুমতি <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-এর আছে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ বা অন্য সংবেদনশীল তথ্য সম্পর্কে সতর্ক থাকুন।"</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"কোনও অ্যাপ আপনার শেয়ার করা, রেকর্ড করা বা কাস্ট করার সময়, সেই অ্যাপে দেখা যায় বা খেলা হয় এমন সব কিছু অ্যাক্সেস করার অনুমতি <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-এর আছে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ বা অন্য সংবেদনশীল তথ্য সম্পর্কে সতর্ক থাকুন।"</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"চালিয়ে যান"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"অ্যাপ শেয়ার বা রেকর্ড করা"</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>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 5e3fb3362719..172b14d8f6d0 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificació en curs d\'una sessió de gravació de la pantalla"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Vols iniciar la gravació?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Durant la gravació, el sistema Android pot capturar qualsevol informació sensible que es mostri a la pantalla o que es reprodueixi al dispositiu. Això inclou contrasenyes, informació de pagament, fotos, missatges i àudio."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Grava la pantalla completa"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Grava una sola aplicació"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Mentre graves, Android té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi al dispositiu. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges o altra informació sensible."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Mentre graves una aplicació, Android té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi a l\'aplicació. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges o altra informació sensible."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Inicia la gravació"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Grava l\'àudio"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Àudio del dispositiu"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"So del dispositiu, com ara música, trucades i sons de trucada"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"El servei que ofereix aquesta funció tindrà accés a tota la informació visible a la teva pantalla o que es reprodueix al dispositiu mentre graves o emets contingut, com ara contrasenyes, detalls dels pagaments, fotos, missatges i àudio que reprodueixis."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Vols començar a gravar o emetre contingut?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Vols començar a gravar o emetre contingut amb <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Vols permetre que <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> comparteixi o gravi?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Tota la pantalla"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Una sola aplicació"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Quan estàs compartint, gravant o emetent, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi al dispositiu. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges o altra informació sensible."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Quan estàs compartint, gravant o emetent, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi a l\'aplicació. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges o altra informació sensible."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continua"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Comparteix o grava una aplicació"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Esborra-ho tot"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Gestiona"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Historial"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index b22656c8787a..034fe9a33eb7 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Trvalé oznámení o relaci nahrávání"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Spustit nahrávání?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Při nahrávání může systém Android zaznamenávat citlivé údaje, které jsou viditelné na obrazovce nebo které jsou přehrávány na zařízení. Týká se to hesel, údajů o platbě, fotek, zpráv a zvuků."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Nahrát celou obrazovku"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Nahrát samostatnou aplikaci"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Během nahrávání má Android přístup k veškerému obsahu, který je viditelný na obrazovce nebo se přehrává v zařízení. Dejte proto pozor na hesla, platební údaje, zprávy nebo jiné citlivé informace."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Během nahrávání aplikace má Android přístup k veškerému obsahu, který je v této aplikaci zobrazen nebo přehráván. Dejte proto pozor na hesla, platební údaje, zprávy nebo jiné citlivé informace."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Spustit nahrávání"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Nahrávat zvuk"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Zvuk zařízení"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Zvuk ze zařízení, například hudba, hovory a vyzvánění"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Služba, která tuto funkci poskytuje, bude mít při nahrávání nebo odesílání přístup ke všem informacím, které jsou viditelné na obrazovce nebo které jsou přehrávány ze zařízení. Týká se to i hesel, údajů o platbě, fotek, zpráv a přehrávaných zvuků."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Začít nahrávat nebo odesílat?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Začít nahrávat nebo odesílat s aplikací <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Povolit aplikaci <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sdílení nebo nahrávání?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Celá obrazovka"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Samostatná aplikace"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Když sdílíte, nahráváte nebo odesíláte obsah, aplikace <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> má přístup k veškerému obsahu, který je viditelný na obrazovce nebo se přehrává v zařízení. Dejte proto pozor na hesla, platební údaje, zprávy nebo jiné citlivé informace."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Když sdílíte, nahráváte nebo odesíláte aplikaci, aplikace <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> má přístup k veškerému obsahu, který je v této aplikaci zobrazen nebo přehráván. Dejte proto pozor na hesla, platební údaje, zprávy nebo jiné citlivé informace."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Pokračovat"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Sdílení nebo nahrání aplikace"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Smazat vše"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Spravovat"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Historie"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 9edb337763b8..03d12aff4ff1 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Konstant notifikation om skærmoptagelse"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Vil du starte optagelse?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Når du optager, kan Android-systemet registrere følsomme oplysninger, der er synlige på din skærm, eller som afspilles på din enhed. Dette inkluderer adgangskoder, betalingsoplysninger, fotos, meddelelser og lyd."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Optag hele skærmen"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Optag én app"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Mens du optager, har Android adgang til alt, der er synligt på din skærm eller afspilles på din enhed. Vær derfor forsigtig med adgangskoder, betalingsoplysninger, beskeder og andre følsomme oplysninger."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Mens du optager en app, har Android adgang til alt, der vises eller afspilles i den pågældende app. Vær derfor forsigtig med adgangskoder, betalingsoplysninger, beskeder og andre følsomme oplysninger."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Start optagelse"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Optag lyd"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Enhedslyd"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Lyd fra din enhed såsom musik, opkald og ringetoner"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Tjenesten, der tilbyder denne funktion, får adgang til alle de oplysninger, der er synlige på din skærm, eller som afspilles på din enhed, når du optager eller caster. Dette omfatter oplysninger som f.eks. adgangskoder, betalingsoplysninger, billeder, beskeder og afspillet lyd."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Vil du begynde at optage eller caste?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Vil du begynde at optage eller caste via <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Vil du tillade, at <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> deler eller optager?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Hele skærmen"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Én app"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Når du deler, optager eller caster, har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> adgang til alt, der er synligt på din skærm eller afspilles på din enhed. Vær derfor forsigtig med adgangskoder, betalingsoplysninger, beskeder og andre følsomme oplysninger."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Når du deler, optager eller caster en app, har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> adgang til alt, der vises eller afspilles i den pågældende app. Vær derfor forsigtig med adgangskoder, betalingsoplysninger, beskeder og andre følsomme oplysninger."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Fortsæt"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Del eller optag en app"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Ryd alle"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Administrer"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Historik"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 76980658f41f..1d13c87fc548 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Fortlaufende Benachrichtigung für eine Bildschirmaufzeichnung"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Aufzeichnung starten?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Beim Aufnehmen kann das Android-System vertrauliche Informationen erfassen, die auf deinem Bildschirm angezeigt oder von deinem Gerät wiedergegeben werden. Das können Passwörter, Zahlungsinformationen, Fotos, Nachrichten und Audioinhalte sein."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Gesamten Bildschirm aufnehmen"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Eine einzelne App aufnehmen"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Während der Aufnahme hat Android Zugriff auf alle Inhalte, die auf dem Bildschirm sichtbar sind oder auf dem Gerät wiedergegeben werden. Sei daher mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen vorsichtig."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Während der Aufnahme einer App hat Android Zugriff auf alle Inhalte, die in dieser App sichtbar sind oder wiedergegeben werden. Sei daher mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen vorsichtig."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Aufnahme starten"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Audio aufnehmen"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio des Geräts"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Audioinhalte auf deinem Gerät, wie Musik, Anrufe und Klingeltöne"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Der Anbieter dieser App erhält Zugriff auf alle Informationen, die auf deinem Bildschirm sichtbar sind oder von deinem Gerät wiedergegeben werden, während du aufnimmst oder streamst. Dazu gehören beispielsweise angezeigte Passwörter, Zahlungsdetails, Fotos, Nachrichten und Audioinhalte."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Aufnahme oder Stream starten?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Aufnehmen oder Streamen mit der App \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" starten?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Zulassen, dass <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> Inhalte teilt oder aufnimmt?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Gesamter Bildschirm"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Eine einzelne App"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Beim Teilen, Aufnehmen oder Übertragen hat <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> Zugriff auf alle Inhalte, die auf dem Bildschirm sichtbar sind oder auf dem Gerät wiedergegeben werden. Sei daher mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen vorsichtig."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Beim Teilen, Aufnehmen oder Übertragen einer App hat <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> Zugriff auf alle Inhalte, die in dieser App sichtbar sind oder wiedergegeben werden. Sei daher mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen vorsichtig."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Weiter"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"App teilen oder aufnehmen"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Alle löschen"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Verwalten"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Verlauf"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index e9d1534442dc..0df5f16c0409 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación continua de una sesión de grabación de la pantalla"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"¿Empezar a grabar?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Mientras grabas, el sistema Android puede capturar información sensible que se muestre o se reproduzca en tu dispositivo, como contraseñas, datos de pago, fotos, mensajes y audio."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Grabar toda la pantalla"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Grabar una sola aplicación"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Mientras grabes contenido, Android podrá acceder a todo lo que sea visible en tu pantalla o que reproduzcas en tu dispositivo. Debes tener cuidado con contraseñas, detalles de pagos, mensajes o cualquier otra información sensible."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Mientras grabes una aplicación, Android podrá acceder a todo lo que muestre o reproduzca la aplicación. Debes tener cuidado con contraseñas, detalles de pagos, mensajes o cualquier otra información sensible."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Iniciar grabación"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Grabar audio"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio del dispositivo"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sonido de tu dispositivo, como música, llamadas y tonos de llamada"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"El servicio que ofrece esta función tendrá acceso a toda la información que se muestre en la pantalla o se reproduzca en el dispositivo mientras grabas o envías contenido, incluyendo contraseñas, detalles de pagos, fotos, mensajes y audios que reproduzcas."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"¿Empezar a grabar o enviar contenido?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"¿Iniciar grabación o el envío de contenido en <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"¿Permitir que <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> comparta o grabe contenido?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Toda la pantalla"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Una sola aplicación"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Cuando compartas, grabes o envíes contenido, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> podrá acceder a todo lo que sea visible en tu pantalla o que reproduzcas en tu dispositivo. Debes tener cuidado con contraseñas, detalles de pagos, mensajes o cualquier otra información sensible."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Cuando compartas, grabes o envíes una aplicación, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> podrá acceder a todo lo que muestre o reproduzca la aplicación. Debes tener cuidado con contraseñas, detalles de pagos, mensajes o cualquier otra información sensible."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continuar"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Compartir o grabar una aplicación"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Borrar todo"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Gestionar"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Historial"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index fae8364fa55b..d42b39704594 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Pooleli märguanne ekraanikuva salvestamise seansi puhul"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Kas alustada salvestamist?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Salvestamise ajal võib Androidi süsteem jäädvustada tundlikku teavet, mis on ekraanikuval nähtav või mida seadmes esitatakse. See hõlmab paroole, makseteavet, fotosid, sõnumeid ja heli."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Kogu ekraanikuva salvestamine"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Ühe rakenduse salvestamine"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Salvestamise ajal on Androidil juurdepääs kõigele, mis on teie ekraanikuval nähtaval või mida teie seadmes esitatakse. Seega olge paroolide, makseteabe, sõnumite ja muu tundliku teabega ettevaatlik."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Rakenduse salvestamise ajal on Androidil juurdepääs kõigele, mis on selles rakenduses nähtaval või mida selles esitatakse. Seega olge paroolide, makseteabe, sõnumite ja muu tundliku teabega ettevaatlik."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Alusta salvestamist"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Heli salvestamine"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Seadme heli"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Seadmest pärinev heli, nt muusika, kõned ja helinad"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Seda funktsiooni pakkuv teenus saab juurdepääsu kogu teabele, mis on teie ekraanikuval nähtav või mida seadmes salvestamise või ülekande ajal esitatakse. See hõlmab teavet, nagu paroolid, maksete üksikasjad, fotod, sõnumid ja esitatav heli."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Kas alustada salvestamist või ülekannet?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Kas alustada rakendusega <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> salvestamist või ülekannet?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Kas lubada rakendusel <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> jagada või salvestada?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Kogu ekraanikuva"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Üks rakendus"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Kui jagate, salvestate või kannate üle, on rakendusel <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> juurdepääs kõigele, mis on teie ekraanikuval nähtaval või mida teie seadmes esitatakse. Seega olge paroolide, makseteabe, sõnumite ja muu tundliku teabega ettevaatlik."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Kui jagate, salvestate või kannate rakendust üle, on rakendusel <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> juurdepääs kõigele, mida selles rakenduses kuvatakse või esitatakse. Seega olge paroolide, makseteabe, sõnumite ja muu tundliku teabega ettevaatlik."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Jätka"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Rakenduse jagamine või salvestamine"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Tühjenda kõik"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Haldamine"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Ajalugu"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index cf53e327b9a5..fc93a800e974 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Pantailaren grabaketa-saioaren jakinarazpen jarraitua"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Grabatzen hasi nahi duzu?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Pantaila grabatzen duzun bitartean, baliteke Android sistemak pantailan agertzen den edo gailuak erreproduzitzen duen kontuzko informazioa grabatzea; besteak beste, pasahitzak, ordainketa-informazioa, argazkiak, mezuak eta audioa."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Grabatu pantaila osoko edukia"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Grabatu aplikazio bakar bat"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Grabatzen ari zarenean, pantailan ikusgai dagoen edo gailuan erreproduzitzen ari den guztirako sarbidea du Android-ek. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin edo bestelako kontuzko informazioarekin."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Aplikazio bat grabatzen ari zarenean, aplikazio horretan ikusgai dagoen edo bertan erreproduzitzen ari den guztirako sarbidea du Android-ek. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin edo bestelako kontuzko informazioarekin."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Hasi grabatzen"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Grabatu audioa"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Gailuaren audioa"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Gailuko soinuak; adibidez, musika, deiak eta tonuak"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Zerbait grabatzen edo igortzen duzunean, pantailan ikus daitekeen edo gailuak erreproduzitzen duen informazio guztia atzitu ahalko du funtzio hori eskaintzen duen zerbitzuak; besteak beste, pasahitzak, ordainketen xehetasunak, argazkiak, mezuak eta erreproduzitzen dituzun audioak."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Grabatzen edo igortzen hasi nahi duzu?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioarekin grabatzen edo igortzen hasi nahi duzu?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Edukia partekatu edo grabatzeko baimena eman nahi diozu <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioari?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Pantaila osoa"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Aplikazio bakar bat"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Edukia partekatzen, grabatzen edo igortzen ari zarenean, pantailan ikusgai dagoen edo gailuan erreproduzitzen ari den guztirako sarbidea du <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin edo bestelako kontuzko informazioarekin."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Aplikazio bat partekatzen, grabatzen edo igortzen ari zarenean, aplikazio horretan ikusgai dagoen edo bertan erreproduzitzen ari den guztirako sarbidea du <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin edo bestelako kontuzko informazioarekin."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Egin aurrera"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Partekatu edo grabatu aplikazioak"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Garbitu guztiak"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Kudeatu"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Historia"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 14a65dc4bcd6..088234281cae 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Pysyvä ilmoitus näytön tallentamisesta"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Aloitetaanko tallennus?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Tallennuksen aikana Android-järjestelmä voi tallentaa mitä tahansa näytöllä näkyvää tai laitteen toistamaa arkaluontoista tietoa. Näitä tietoja ovat esimerkiksi salasanat, maksutiedot, kuvat, viestit ja audio."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Tallenna koko näyttö"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Tallenna yhtä sovellusta"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Kun tallennat, Android saa pääsyn kaikkeen näytölläsi näkyvään tai laitteellasi toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä tai muita arkaluontoisia tietoja."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Kun tallennat sovellusta, Android saa pääsyn kaikkeen sovelluksessa näkyvään tai toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä tai muita arkaluontoisia tietoja."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Aloita tallennus"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Tallenna audiota"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Laitteen audio"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Musiikki, puhelut, soittoäänet ja muut äänet laitteesta"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Ominaisuuden tarjoavalla palvelulla on pääsy kaikkiin näytölläsi näkyviin tietoihin ja tietoihin laitteesi toistamasta sisällöstä tallennuksen tai striimauksen aikana. Näitä tietoja ovat esimerkiksi salasanat, maksutiedot, kuvat, viestit ja toistettava audiosisältö."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Aloitetaanko tallentaminen tai striimaus?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Haluatko, että <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aloittaa tallennuksen tai striimauksen?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Sallitaanko, että <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> jaetaan tai tallennetaan?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Koko näyttö"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Yksittäinen sovellus"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Kun jaat, tallennat tai striimaat, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> saa pääsyn kaikkeen näytölläsi näkyvään tai laitteellasi toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä tai muita arkaluontoisia tietoja."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Kun jaat, tallennat tai striimaat sovellusta, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> saa pääsyn kaikkeen sovelluksessa näkyvään tai toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä tai muita arkaluontoisia tietoja."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Jatka"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Jaa sovellus tai tallenna sen sisältöä"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Tyhjennä kaikki"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Muuta asetuksia"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Historia"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 9fdae3e3f0a8..a80b03791bd9 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement de l\'écran"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Démarrer l\'enregistrement ?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Durant l\'enregistrement, le système Android peut capturer les infos sensibles affichées à l\'écran ou lues sur votre appareil. Cela inclut les mots de passe, les infos de paiement, les photos, les messages et l\'audio."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Enregistrer tout l\'écran"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Enregistrer une seule appli"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Lorsque vous enregistrez une appli, Android à accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention à vos mots de passe, détails de mode de paiement, messages ou autres informations sensibles."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Lorsque vous enregistrez une appli, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention à vos mots de passe, détails de mode de paiement, messages ou autres informations sensibles."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Lancer l\'enregistrement"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Enregistrer l\'audio"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio de l\'appareil"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Son provenant de l\'appareil (musique, appels et sonneries, etc.)"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Le service qui fournit cette fonction aura accès à toutes les infos visibles sur votre écran ou lues depuis votre appareil lors d\'un enregistrement ou de la diffusion d\'un contenu. Cela comprend, entre autres, vos mots de passe, les détails de vos paiements, vos photos, vos messages ou les contenus audio que vous écoutez."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Démarrer l\'enregistrement ou la diffusion ?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Démarrer l\'enregistrement ou la diffusion avec <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Autoriser <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> à partager ou enregistrer ?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Tout l\'écran"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Une seule appli"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Lorsque vous partagez, enregistrez ou castez, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention à vos mots de passe, détails de mode de paiement, messages ou autres informations sensibles."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Lorsque vous partagez, enregistrez ou castez une appli, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention à vos mots de passe, détails de mode de paiement, messages ou autres informations sensibles."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continuer"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Partager ou enregistrer une appli"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Tout effacer"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Gérer"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Historique"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 36036aaf06b9..bb3894aa21e6 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación en curso sobre unha sesión de gravación de pantalla"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Queres iniciar a gravación?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Durante a gravación, o sistema Android pode captar información confidencial que apareza na pantalla ou se reproduza no dispositivo, como contrasinais, información de pago, fotos, mensaxes e audio."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Gravar pantalla completa"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Gravar unha soa aplicación"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Durante a gravación, Android ten acceso a todo o que se vexa na pantalla ou se reproduza no teu dispositivo. Polo tanto, debes ter coidado cos contrasinais, os detalles de pago, as mensaxes ou outra información confidencial."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Cando gravas unha aplicación, Android ten acceso a todo o que se vexa ou se reproduza nela. Polo tanto, debes ter coidado cos contrasinais, os detalles de pago, as mensaxes ou outra información confidencial."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Iniciar gravación"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Gravar audio"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio do dispositivo"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Son do dispositivo (por exemplo, música, chamadas e tons de chamada)"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"O servizo que proporciona esta función terá acceso a toda a información visible na pantalla ou reproducida desde o teu dispositivo mentres graves ou emitas contido. Isto inclúe información como contrasinais, detalles de pago, fotos, mensaxes e o audio que reproduzas."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Queres iniciar a gravación ou a emisión?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Queres comezar a gravar ou emitir contido con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Queres permitir que <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> comparta ou grave contido?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Pantalla completa"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Unha soa aplicación"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Cando compartes, gravas ou emites contido, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ten acceso a todo o que se vexa na pantalla ou se reproduza no teu dispositivo. Polo tanto, debes ter coidado cos contrasinais, os detalles de pago, as mensaxes ou outra información confidencial."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Cando compartes, gravas ou emites unha aplicación, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ten acceso a todo o que se vexa ou se reproduza nela. Polo tanto, debes ter coidado cos contrasinais, os detalles de pago, as mensaxes ou outra información confidencial."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continuar"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Compartir ou gravar unha aplicación"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Eliminar todas"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Xestionar"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Historial"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 3d1b1ea56fb9..9dc6f67b1b93 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रिकॉर्ड सेशन के लिए जारी सूचना"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"क्या आपको रिकॉर्डिंग शुरू करनी है?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"रिकॉर्ड करते समय, Android सिस्टम आपकी स्क्रीन पर दिखने वाली या चलाई जाने वाली संवेदनशील जानकारी को कैप्चर कर सकता है. इसमें पासवर्ड, पैसे चुकाने से जुड़ी जानकारी, फ़ोटो, मैसेज, और ऑडियो शामिल हैं."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"पूरी स्क्रीन रिकॉर्ड करें"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"सिर्फ़ एक ऐप्लिकेशन रिकॉर्ड करें"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Android के पास, रिकॉर्ड करने के दौरान, स्क्रीन पर दिख रही हर चीज़ या डिवाइस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, शेयर, रिकॉर्ड या कास्ट करते समय, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज या किसी और संवेदनशील जानकारी को लेकर खास सावधानी बरतें."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"कोई ऐप्लिकेशन रिकॉर्ड करने के दौरान, Android के पास उस पर दिख रही हर चीज़ या उस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज या किसी और संवेदनशील जानकारी को लेकर खास सावधानी बरतें."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"रिकॉर्ड करना शुरू करें"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"ऑडियो रिकॉर्ड करें"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"डिवाइस ऑडियो"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"आपके डिवाइस से आने वाली आवाज़ जैसे कि संगीत, कॉल, और रिंगटोन"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> को शेयर या रिकॉर्ड करने की अनुमति दें?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"पूरी स्क्रीन"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"सिर्फ़ एक ऐप्लिकेशन"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"शेयर, रिकॉर्ड या कास्ट करते समय, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> के पास स्क्रीन पर दिख रही हर चीज़ या डिवाइस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, शेयर, रिकॉर्ड या कास्ट करते समय, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज या किसी और संवेदनशील जानकारी को लेकर खास सावधानी बरतें."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"शेयर, रिकॉर्ड या कास्ट करते समय, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> के पास उस ऐप्लिकेशन पर दिख रही हर चीज़ या उस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, शेयर, रिकॉर्ड या कास्ट करते समय, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज या किसी और संवेदनशील जानकारी को लेकर खास सावधानी बरतें."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"जारी रखें"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"ऐप्लिकेशन शेयर करें या उसकी रिकॉर्डिंग करें"</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>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index fed009f42025..5e5e249fc415 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Էկրանի տեսագրման աշխատաշրջանի ընթացիկ ծանուցում"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Սկսե՞լ տեսագրումը"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Տեսագրման ընթացքում Android համակարգը կարող է գրանցել անձնական տեղեկություններ, որոնք տեսանելի են էկրանին կամ նվագարկվում են ձեր սարքում։ Սա ներառում է այնպիսի տեղեկություններ, ինչպիսիք են, օրինակ, գաղտնաբառերը, վճարային տվյալները, լուսանկարները, հաղորդագրությունները և նվագարկվող աուդիո ֆայլերը։"</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Տեսագրել ամբողջ էկրանը"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Տեսագրել մեկ հավելված"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Երբ դուք տեսագրում եք էկրանը, Android-ին հասանելի է դառնում այն ամենը, ինչ տեսանելի է էկրանին և նվագարկվում է ձեր սարքում։ Հիշեք այդ մասին, երբ պատրաստվում եք դիտել կամ մուտքագրել գաղտնաբառեր, վճարային տվյալներ, հաղորդագրություններ և այլ կոնֆիդենցիալ տեղեկություններ։"</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Երբ դուք տեսագրում եք որևէ հավելվածի էկրանը, Android-ին հասանելի է դառնում այն ամենը, ինչ ցուցադրվում է կամ նվագարկվում այդ հավելվածում։ Հիշեք այդ մասին, երբ պատրաստվում եք դիտել կամ մուտքագրել գաղտնաբառեր, վճարային տվյալներ, հաղորդագրություններ և այլ կոնֆիդենցիալ տեղեկություններ։"</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Սկսել տեսագրումը"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Ձայնագրել"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Սարքի ձայները"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Ձեր սարքի ձայները, օրինակ՝ երաժշտությունը, զանգերն ու զանգերանգները"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Թույլատրե՞լ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածին ցուցադրել կամ տեսագրել էկրանը"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Ամբողջ էկրանը"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Մեկ հավելված"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Երբ դուք ցուցադրում, տեսագրում կամ հեռարձակում եք էկրանը, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածին հասանելի է դառնում այն ամենը, ինչ տեսանելի է էկրանին և նվագարկվում է ձեր սարքում։ Հիշեք այդ մասին, երբ պատրաստվում եք դիտել կամ մուտքագրել գաղտնաբառեր, վճարային տվյալներ, հաղորդագրություններ և այլ կոնֆիդենցիալ տեղեկություններ։"</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Երբ դուք ցուցադրում, տեսագրում կամ հեռարձակում եք որևէ հավելվածի էկրանը, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածին հասանելի է դառնում այն ամենը, ինչ ցուցադրվում է կամ նվագարկվում այդ հավելվածում։ Հիշեք այդ մասին, երբ պատրաստվում եք դիտել կամ մուտքագրել գաղտնաբառեր, վճարային տվյալներ, հաղորդագրություններ և այլ կոնֆիդենցիալ տեղեկություններ։"</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Շարունակել"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Հավելվածի էկրանի ցուցադրում կամ տեսագրում"</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>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 01569000b915..e372c3735478 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifikasi yang sedang berjalan untuk sesi rekaman layar"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Mulai merekam?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Saat merekam, Sistem Android dapat ikut merekam informasi sensitif yang terlihat di layar atau diputar di perangkat Anda. Informasi ini mencakup sandi, info pembayaran, foto, pesan, dan audio."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Rekam seluruh layar"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Rekam satu aplikasi"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Saat Anda merekam, Android akan memiliki akses ke semua hal yang ditampilkan di layar atau yang diputar di perangkat Anda. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, atau informasi sensitif lainnya."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Saat Anda merekam aplikasi, Android akan memiliki akses ke semua hal yang ditampilkan atau yang diputar di aplikasi tersebut. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, atau informasi sensitif lainnya."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Mulai merekam"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Rekam audio"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio perangkat"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Suara dari perangkat Anda, seperti musik, panggilan, dan nada dering"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Layanan yang menyediakan fungsi ini akan memiliki akses ke semua informasi yang terlihat di layar atau diputar dari perangkat saat merekam atau melakukan transmisi. Ini mencakup informasi seperti sandi, detail pembayaran, foto, pesan, dan audio yang Anda putar."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Mulai merekam atau melakukan transmisi?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Mulai merekam atau melakukan transmisi dengan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Izinkan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> untuk membagikan atau merekam?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Seluruh layar"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Satu aplikasi"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Jika Anda membagikan, merekam, atau mentransmisikan, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> akan memiliki akses ke semua hal yang ditampilkan di layar atau yang diputar di perangkat Anda. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, atau informasi sensitif lainnya."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Jika Anda membagikan, merekam, atau mentransmisikan suatu aplikasi, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> akan memiliki akses ke semua hal yang ditampilkan atau yang diputar di aplikasi tersebut. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, atau informasi sensitif lainnya."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Lanjutkan"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Bagikan atau rekam aplikasi"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Hapus semua"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Kelola"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Histori"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 7622ad4ed87b..136db9e92afc 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Áframhaldandi tilkynning fyrir skjáupptökulotu"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Hefja upptöku?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Á meðan tekið er upp getur Android kerfið fangað viðkvæmar upplýsingar sem sjást á skjánum eða spilast í tækinu. Þar á meðal eru upplýsingar á borð við aðgangsorð, greiðsluupplýsingar, myndir, skilaboð og hljóð."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Taka upp allan skjáinn"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Taka upp eitt forrit"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Þegar þú tekur upp hefur Android aðgang að öllu sem sést á skjánum eða spilast í tækinu. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð eða aðrar viðkvæmar upplýsingar."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Þegar þú tekur upp forrit hefur Android aðgang að öllu sem sést eða spilast í viðkomandi forriti. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð eða aðrar viðkvæmar upplýsingar."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Hefja upptöku"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Taka upp hljóð"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Hljóð tækis"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Hljóð úr tækinu á borð við tónlist, símtöl og hringitóna"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Þjónustan sem býður upp á þennan eiginleika fær aðgang að öllum upplýsingum sem sjást á skjánum eða eru spilaðar í tækinu á meðan upptaka eða útsending er í gangi, þar á meðal aðgangsorði, greiðsluupplýsingum, myndum, skilaboðum og hljóðefni sem þú spilar."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Viltu hefja upptöku eða útsendingu?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Viltu hefja upptöku eða útsendingu með <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Leyfa <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> að deila eða taka upp?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Allur skjárinn"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Eitt forrit"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Þegar þú deilir, tekur upp eða sendir út hefur<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aðgang að öllu sem sést á skjánum eða spilast í tækinu. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð eða aðrar viðkvæmar upplýsingar."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Þegar þú deilir, tekur upp eða sendir út forrit hefur <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aðgang að öllu sem sést eða spilast í viðkomandi forriti. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð eða aðrar viðkvæmar upplýsingar."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Áfram"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Deila eða taka upp forrit"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Hreinsa allt"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Stjórna"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Ferill"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index d6631e7683b0..df3e6fd6007c 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды бейнеге жазудың ағымдағы хабарландыруы"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Жазу басталсын ба?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Android жүйесі экранда көрсетілетін немесе құрылғыда ойнатылатын құпия ақпаратты жазып алуы мүмкін. Ондай ақпаратқа құпия сөздер, төлем ақпараты, фотосуреттер, хабарлар және аудио жатады."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Бүкіл экранды жазу"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Жалғыз қолданбаны жазу"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Жазу кезінде Android жүйесі экраныңызда көрінетін не құрылғыңызда ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізу кезінде сақ болыңыз."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Қолданба экранын жазу кезінде Android жүйесі қолданбада көрінетін не ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізу кезінде сақ болыңыз."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Жазуды бастау"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Аудио жазу"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Құрылғыдан шығатын дыбыс"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Музыка, қоңыраулар және рингтондар сияқты құрылғыдан шығатын дыбыс"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> қолданбасына экранды бөлісуге не жазуға рұқсат берілсін бе?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Бүкіл экран"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Жалғыз қолданба"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Бөлісу, жазу не трансляциялау кезінде <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> қолданбасы экраныңызда көрінетін не құрылғыңызда ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізу кезінде сақ болыңыз."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Қолданба экранын бөлісу, жазу не трансляциялау кезінде <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> қолданбасы онда көрінетін не ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізу кезінде сақ болыңыз."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Жалғастыру"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Қолданба экранын бөлісу не жазу"</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>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 713d20d130fe..83a5e87260ca 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಸೆಶನ್‌ಗಾಗಿ ಚಾಲ್ತಿಯಲ್ಲಿರುವ ಅಧಿಸೂಚನೆ"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"ರೆಕಾರ್ಡಿಂಗ್ ಪ್ರಾರಂಭಿಸಬೇಕೆ?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"ರೆಕಾರ್ಡಿಂಗ್ ಸಮಯದಲ್ಲಿ, ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ಗೋಚರಿಸುವ ಅಥವಾ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲಾದ ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯನ್ನು Android ಸಿಸ್ಟಂ ಕ್ಯಾಪ್ಚರ್ ಮಾಡಬಹುದು. ಇದು ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ಮಾಹಿತಿ, ಫೋಟೋಗಳು, ಸಂದೇಶಗಳು ಮತ್ತು ಆಡಿಯೋವನ್ನು ಒಳಗೊಂಡಿದೆ."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"ಸಂಪೂರ್ಣ ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"ಒಂದೇ ಆ್ಯಪ್ ಅನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"ನೀವು ರೆಕಾರ್ಡ್ ಮಾಡುತ್ತಿರುವಾಗ, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಕಾಣಿಸುವ ಅಥವಾ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಆಗುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ Android ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಹಾಗಾಗಿ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು ಅಥವಾ ಇತರ ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡುತ್ತಿರುವಾಗ, ಆ ಆ್ಯಪ್‌ನಲ್ಲಿ ತೋರಿಸಲಾಗುವ ಅಥವಾ ಪ್ಲೇ ಆಗುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ Android ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಹಾಗಾಗಿ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು ಅಥವಾ ಇತರ ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"ರೆಕಾರ್ಡಿಂಗ್ ಪ್ರಾರಂಭಿಸಿ"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"ಆಡಿಯೋ ರೆಕಾರ್ಡ್‌ ಮಾಡಿ"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"ಸಾಧನದ ಆಡಿಯೋ"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"ನಿಮ್ಮ ಸಾಧನದ ಧ್ವನಿ ಉದಾ: ಸಂಗೀತ, ಕರೆಗಳು ಮತ್ತು ರಿಂಗ್‌ಟೋನ್‌ಗಳು"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"ಹಂಚಿಕೊಳ್ಳಲು ಅಥವಾ ರೆಕಾರ್ಡ್ ಮಾಡಲು <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಅನ್ನು ಅನುಮತಿಸಬೇಕೆ?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"ಸಂಪೂರ್ಣ ಸ್ಕ್ರೀನ್"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"ಒಂದೇ ಆ್ಯಪ್"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"ನೀವು ಹಂಚಿಕೊಳ್ಳುತ್ತಿರುವಾಗ, ರೆಕಾರ್ಡ್ ಮಾಡುತ್ತಿರುವಾಗ ಅಥವಾ ಬಿತ್ತರಿಸುತ್ತಿರುವಾಗ, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಕಾಣಿಸುವ ಅಥವಾ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಆಗುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಹಾಗಾಗಿ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು ಅಥವಾ ಇತರ ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳುತ್ತಿರುವಾಗ, ರೆಕಾರ್ಡ್ ಮಾಡುತ್ತಿರುವಾಗ ಅಥವಾ ಬಿತ್ತರಿಸುತ್ತಿರುವಾಗ, ಆ ಆ್ಯಪ್‌ನಲ್ಲಿ ತೋರಿಸಲಾಗುವ ಅಥವಾ ಪ್ಲೇ ಆಗುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಹಾಗಾಗಿ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು ಅಥವಾ ಇತರ ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"ಮುಂದುವರಿಸಿ"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"ಆ್ಯಪ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ ಅಥವಾ ರೆಕಾರ್ಡ್ ಮಾಡಿ"</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>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 290c51724ec7..f3fb7a085549 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"화면 녹화 세션에 관한 지속적인 알림"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"녹화를 시작하시겠습니까?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Android 시스템이 녹화 중에 화면에 표시되거나 기기에서 재생되는 민감한 정보를 캡처할 수 있습니다. 여기에는 비밀번호, 결제 정보, 사진, 메시지 및 오디오가 포함됩니다."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"전체 화면 녹화"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"단일 앱 녹화"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"녹화할 때 Android에서 화면에 표시되거나 기기에서 재생되는 모든 항목에 액세스할 수 있습니다. 따라서 비밀번호, 결제 세부정보, 메시지 등 민감한 정보가 노출되지 않도록 주의하세요."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"앱을 녹화할 때 Android에서 해당 앱에서 표시되거나 재생되는 모든 항목에 액세스할 수 있으므로 비밀번호, 결제 세부정보, 메시지 등 민감한 정보가 노출되지 않도록 주의하세요."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"녹화 시작"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"오디오 녹음"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"기기 오디오"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"음악, 통화, 벨소리와 같이 기기에서 나는 소리"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>에서 공유 또는 녹화를 허용할까요?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"전체 화면"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"단일 앱"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"공유하거나 녹화하거나 전송할 때 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 앱에서 화면에 표시되거나 기기에서 재생되는 모든 항목에 액세스할 수 있습니다. 따라서 비밀번호, 결제 세부정보, 메시지 등 민감한 정보가 노출되지 않도록 주의하세요."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"앱을 공유하거나 녹화하거나 전송할 때는 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>에서 해당 앱에 표시되거나 재생되는 모든 항목에 액세스할 수 있으므로 비밀번호, 결제 세부정보, 메시지 등 민감한 정보가 노출되지 않도록 주의하세요."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"계속"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"앱 공유 또는 녹화"</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>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 9cb8bfdff771..5a63b626c81c 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Aktīvs paziņojums par ekrāna ierakstīšanas sesiju"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Vai sākt ierakstīšanu?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Ierakstīšanas laikā Android sistēmā var tikt tverta jebkura sensitīvā informācija, kas ir redzama jūsu ekrānā vai tiek atskaņota jūsu ierīcē. Šī informācija ir paroles, maksājumu informācija, fotoattēli, ziņojumi un audio."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Ierakstīt visu ekrānu"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Ierakstīt vienu lietotni"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Ierakstīšanas laikā Android var piekļūt visam, kas tiek rādīts jūsu ekrānā vai atskaņots jūsu ierīcē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem un citu sensitīvu informāciju."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Lietotnes ierakstīšanas laikā Android var piekļūt visam, kas tiek rādīts vai atskaņots attiecīgajā lietotnē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem un citu sensitīvu informāciju."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Sākt ierakstīšanu"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Ierakstīt audio"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Ierīces audio"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Skaņa no jūsu ierīces, piemēram, mūzika, sarunas un zvana signāli"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Pakalpojums, kas nodrošina šo funkciju, iegūs piekļuvi visai informācijai, kas ierakstīšanas vai apraides laikā tiks rādīta jūsu ekrānā vai atskaņota jūsu ierīcē. Atļauja attiecas uz tādu informāciju kā paroles, maksājumu informācija, fotoattēli, ziņojumi un jūsu atskaņotais audio saturs."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Vai vēlaties sākt ierakstīšanu/apraidi?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Vai vēlaties sākt ierakstīšanu vai apraidi, izmantojot lietotni <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Vai atļaujat lietotnei <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> veikt kopīgošanu vai ierakstīšanu?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Viss ekrāns"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Viena lietotne"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Kopīgošanas, ierakstīšanas vai apraides laikā <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> var piekļūt visam, kas tiek rādīts jūsu ekrānā vai atskaņots jūsu ierīcē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem un citu sensitīvu informāciju."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Lietotnes kopīgošanas, ierakstīšanas vai apraides laikā <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> var piekļūt visam, kas tiek rādīts vai atskaņots attiecīgajā lietotnē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem un citu sensitīvu informāciju."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Turpināt"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Lietotnes kopīgošana vai ierakstīšana"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Dzēst visu"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Pārvaldīt"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Vēsture"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index bf1c262008fc..7611822c689c 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ഒരു സ്ക്രീൻ റെക്കോർഡിംഗ് സെഷനായി നിലവിലുള്ള അറിയിപ്പ്"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"റെക്കോർഡിംഗ് ആരംഭിക്കണോ?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"റെക്കോർഡ് ചെയ്യുമ്പോൾ, നിങ്ങളുടെ സ്‌ക്രീനിൽ ദൃശ്യമാകുന്നതോ ഉപകരണത്തിൽ പ്ലേ ചെയ്യുന്നതോ ആയ ഏത് തന്ത്രപ്രധാന വിവരങ്ങളും Android സിസ്റ്റത്തിന് പകർത്താനാവും. പാസ്‍വേഡുകൾ, പേയ്‌മെന്റ് വിവരം, ഫോട്ടോകൾ, സന്ദേശങ്ങൾ, ഓഡിയോ എന്നിവ ഇതിൽ ഉൾപ്പെടുന്നു."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"പൂർണ സ്ക്രീൻ റെക്കോർഡ് ചെയ്യൂ"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"ഒറ്റ ആപ്പ് റെക്കോർഡ് ചെയ്യുക"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"റെക്കോർഡ് ചെയ്യുമ്പോൾ, Android-ന് സ്ക്രീനിൽ ദൃശ്യമാകുന്നതോ ഉപകരണത്തിൽ പ്ലേ ചെയ്യുന്നതോ ആയ ഏത് കാര്യത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ, പാസ്‍വേഡുകൾ, പേയ്‌മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ അല്ലെങ്കിൽ സൂക്ഷ്‌മമായി കൈകാര്യം ചെയ്യേണ്ട മറ്റു വിവരങ്ങൾ എന്നിവ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"ഒരു ആപ്പ് റെക്കോർഡ് ചെയ്യുമ്പോൾ, Android-ന് ആ ആപ്പിൽ കാണിക്കുന്നതോ പ്ലേ ചെയ്യുന്നതോ ആയ എല്ലാത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ, പാസ്‍വേഡുകൾ, പേയ്‌മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ അല്ലെങ്കിൽ സൂക്ഷ്‌മമായി കൈകാര്യം ചെയ്യേണ്ട മറ്റു വിവരങ്ങൾ എന്നിവ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"റെക്കോർഡിംഗ് ആരംഭിക്കുക"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"ഓഡിയോ റെക്കോർഡ് ചെയ്യുക"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"ഉപകരണത്തിന്റെ ഓഡിയോ"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"സംഗീതം, കോളുകൾ, റിംഗ്‌ടോണുകൾ എന്നിവപോലെ നിങ്ങളുടെ ഉപകരണത്തിൽ നിന്നുള്ള ശബ്ദം"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"പങ്കിടാനോ റെക്കോർഡ് ചെയ്യാനോ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിനെ അനുവദിക്കണോ?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"മുഴുവൻ സ്‌ക്രീൻ"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"ഒറ്റ ആപ്പ്"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"പങ്കിടുമ്പോൾ, റെക്കോർഡ് ചെയ്യുമ്പോൾ അല്ലെങ്കിൽ കാസ്റ്റ് ചെയ്യുമ്പോൾ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിന് നിങ്ങളുടെ സ്ക്രീനിൽ ദൃശ്യമാകുന്നതോ ഉപകരണത്തിൽ പ്ലേ ചെയ്യുന്നതോ ആയ ഏത് കാര്യത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ, പാസ്‍വേഡുകൾ, പേയ്‌മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ അല്ലെങ്കിൽ സൂക്ഷ്‌മമായി കൈകാര്യം ചെയ്യേണ്ട മറ്റു വിവരങ്ങൾ എന്നിവ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"ഒരു ആപ്പ് പങ്കിടുമ്പോൾ, റെക്കോർഡ് ചെയ്യുമ്പോൾ അല്ലെങ്കിൽ കാസ്റ്റ് ചെയ്യുമ്പോൾ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിന് ആപ്പിൽ കാണിക്കുന്ന അല്ലെങ്കിൽ പ്ലേ ചെയ്യുന്ന എല്ലാത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ, പാസ്‍വേഡുകൾ, പേയ്‌മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ അല്ലെങ്കിൽ സൂക്ഷ്‌മമായി കൈകാര്യം ചെയ്യേണ്ട മറ്റു വിവരങ്ങൾ എന്നിവ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"തുടരുക"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"ഒരു ആപ്പ് പങ്കിടുക അല്ലെങ്കിൽ റെക്കോർഡ് ചെയ്യുക"</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>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index f7b8ef0446d4..2f96f3397306 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रेकॉर्ड सत्रासाठी सुरू असलेली सूचना"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"रेकॉर्डिंग सुरू करायचे आहे का?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"रेकॉर्डिंग करताना, Android सिस्टीम तुमच्या स्क्रीनवर दिसणारी किंवा तुमच्या डिव्हाइसवर प्ले केलेली कोणतीही संवेदनशील माहिती कॅप्चर करू शकते. यात पासवर्ड, पेमेंट माहिती, फोटो, मेसेज आणि ऑडिओचा समावेश आहे."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"संपूर्ण स्क्रीन रेकॉर्ड करा"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"एकच अ‍ॅप रेकॉर्ड करा"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"तुम्ही रेकॉर्ड करत असताना, Android ला तुमच्या स्क्रीनवर दाखवलेल्या किंवा डिव्हाइसवर प्ले केलेल्या कोणत्याही गोष्टीचा अ‍ॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज किंवा इतर संवेदनशील माहिती काळजीपूर्वक वापरा."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"तुम्ही अ‍ॅप रेकॉर्ड करत असताना, Android ला त्या अ‍ॅपवर दाखवलेल्या किंवा प्ले केलेल्या कोणत्याही गोष्टीचा अ‍ॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज किंवा इतर संवेदनशील माहिती काळजीपूर्वक वापरा."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"रेकॉर्डिंग सुरू करा"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"ऑडिओ रेकॉर्ड करा"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"डिव्हाइस ऑडिओ"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"तुमच्या डिव्हाइसवरील आवाज, जसे की संगीत, कॉल आणि रिंगटोन"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ला शेअर किंवा रेकॉर्ड करण्याची अनुमती द्यायची आहे का?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"संपूर्ण स्क्रीन"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"एक अ‍ॅप"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"तुम्ही शेअर, रेकॉर्ड किंवा कास्ट करत असताना, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ला तुमच्या स्क्रीनवर दाखवलेल्या किंवा डिव्हाइसवर प्ले केलेल्या कोणत्याही गोष्टीचा अ‍ॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज किंवा इतर संवेदनशील माहिती काळजीपूर्वक वापरा."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"तुम्ही अ‍ॅप शेअर, रेकॉर्ड किंवा कास्ट करत असताना, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ला त्या अ‍ॅपवर दाखवलेल्या किंवा प्ले केलेल्या कोणत्याही गोष्टीचा अ‍ॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज किंवा इतर संवेदनशील माहिती काळजीपूर्वक वापरा."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"पुढे सुरू ठेवा"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"अ‍ॅप शेअर किंवा रेकॉर्ड करा"</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>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index a874e4588e25..fe1b908e098b 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ဖန်သားပြင် ရိုက်ကူးသည့် စက်ရှင်အတွက် ဆက်တိုက်လာနေသော အကြောင်းကြားချက်"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"စတင် ရိုက်ကူးမလား။"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"ရိုက်ကူးနေစဉ်အတွင်း Android စနစ်သည် သင့်ဖန်သားပြင်ပေါ်တွင် မြင်နိုင်သော (သို့) သင့်စက်ပစ္စည်းတွင် ဖွင့်ထားသော အရေးကြီးသည့် အချက်အလက်များကို ရိုက်ယူနိုင်သည်။ ၎င်းတွင် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ ဓာတ်ပုံ၊ မက်ဆေ့ဂျ်နှင့် အသံများ ပါဝင်သည်။"</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"ဖန်သားပြင်တစ်ခုလုံးရိုက်ကူးရန်"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"အက်ပ်တစ်ခုတွင် ရိုက်ကူးရန်"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"ရိုက်ကူးနေစဉ် Android သည် သင့်ဖန်သားပြင်ရှိ မြင်နိုင်သည့် (သို့) သင့်စက်တွင် ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ ထို့ကြောင့် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ် (သို့) အခြားအရေးကြီးအချက်အလက်များနှင့်ပတ်သက်၍ ဂရုစိုက်ပါ။"</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"အက်ပ်တစ်ခုကို ရိုက်ကူးနေစဉ် Android သည် ၎င်းအက်ပ်တွင် ပြထားသည့် (သို့) ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ ထို့ကြောင့် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ် (သို့) အခြားအရေးကြီးအချက်အလက်များနှင့်ပတ်သက်၍ ဂရုစိုက်ပါ။"</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"စတင်ရိုက်ကူးရန်"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"အသံဖမ်းရန်"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"စက်ပစ္စည်းအသံ"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"သီချင်း၊ ဖုန်းခေါ်ဆိုမှုနှင့် ဖုန်းမြည်သံကဲ့သို့ သင့်စက်ပစ္စည်းမှ အသံ"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"မျှဝေရန် (သို့) ရိုက်ကူးရန် <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ကို ခွင့်ပြုမလား။"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"ဖန်သားပြင်တစ်ခုလုံး"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"အက်ပ်တစ်ခုတွင်"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"မျှဝေ၊ ရိုက်ကူး (သို့) ကာစ်လုပ်သည့်အခါ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> သည် သင့်ဖန်သားပြင်ရှိ မြင်နိုင်သည့် (သို့) သင့်စက်တွင် ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ ထို့ကြောင့် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ် (သို့) အခြားအရေးကြီးအချက်အလက်များနှင့်ပတ်သက်၍ ဂရုစိုက်ပါ။"</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"အက်ပ်ဖြင့် မျှဝေ၊ ရိုက်ကူး (သို့) ကာစ်လုပ်သည့်အခါ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> သည် ၎င်းအက်ပ်တွင် ပြထားသည့် (သို့) ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ ထို့ကြောင့် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ် (သို့) အခြားအရေးကြီးအချက်အလက်များနှင့်ပတ်သက်၍ ဂရုစိုက်ပါ။"</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"ရှေ့ဆက်ရန်"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"အက်ပ် မျှဝေခြင်း (သို့) ရိုက်ကူးခြင်း"</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>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 6dd9d8f4b7f1..951eb8c46436 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Vedvarende varsel for et skjermopptak"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Vil du starte et opptak?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Under opptak kan Android-systemet registrere all sensitiv informasjon som er synlig på skjermen eller spilles av på enheten. Dette inkluderer passord, betalingsinformasjon, bilder, meldinger og lyd."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Ta opp hele skjermen"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Ta opp én app"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Når du tar opp noe, har Android tilgang til alt som vises på skjermen eller spilles av på enheten. Derfor bør du være forsiktig med passord, betalingsopplysninger, meldinger og annen sensitiv informasjon."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Når du tar opp en app, har Android tilgang til alt som vises eller spilles av i appen. Derfor bør du være forsiktig med passord, betalingsopplysninger, meldinger og annen sensitiv informasjon."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Start opptaket"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Spill inn lyd"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Enhetslyd"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Lyd fra enheten, f.eks. musikk, samtaler og ringelyder"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Tjenesten som leverer denne funksjonen, får tilgang til all informasjon som er synlig på skjermen din, eller som spilles av fra enheten når du tar opp eller caster. Dette inkluderer informasjon som passord, betalingsopplysninger, bilder, meldinger og lyd du spiller av."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Vil du starte opptak eller casting?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Vil du starte opptak eller casting med <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Vil du gi <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tillatelse til å dele eller ta opp?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Hele skjermen"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Én app"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Når du deler, tar opp eller caster noe, har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tilgang til alt som vises på skjermen eller spilles av på enheten. Derfor bør du være forsiktig med passord, betalingsopplysninger, meldinger og annen sensitiv informasjon."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Når du deler, tar opp eller caster en app, har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tilgang til alt som vises eller spilles av i den aktuelle appen. Derfor bør du være forsiktig med passord, betalingsopplysninger, meldinger og annen sensitiv informasjon."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Fortsett"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Del eller ta opp en app"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Fjern alt"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Administrer"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Logg"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 2362b401df7d..35112a7b1a03 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"कुनै स्क्रिन रेकर्ड गर्ने सत्रका लागि चलिरहेको सूचना"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"रेकर्ड गर्न थाल्ने हो?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"रेकर्ड गर्दा, Android सिस्टमले तपाईंको स्क्रिनमा देखिने वा तपाईंको डिभाइसमा प्ले गरिने सबै संवेदनशील जानकारी रेकर्ड गर्न सक्छ। यो जानकारीमा पासवर्ड, भुक्तानीसम्बन्धी जानकारी, फोटो, सन्देश र अडियो समावेश हुन्छ।"</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"पूरै स्क्रिन रेकर्ड गर्नुहोस्"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"एउटा एप मात्र रेकर्ड गर्नुहोस्"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"तपाईंले रेकर्ड गर्दा Android ले तपाईंको स्क्रिनमा देखिने वा डिभाइसमा प्ले गरिएका सबै कुरा खिच्न सक्छ। त्यसैले रेकर्ड गर्दा पासवर्ड, भुक्तानीको विवरण, म्यासेज वा अन्य संवेदनशील जानकारी सुरक्षित राख्नुहोला।"</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"तपाईंले रेकर्ड गर्दा Android ले तपाईंको स्क्रिनमा देखिने वा डिभाइसमा प्ले गरिएका सबै कुरा खिच्न सक्छ। त्यसैले रेकर्ड गर्दा पासवर्ड, भुक्तानीको विवरण, म्यासेज वा अन्य संवेदनशील जानकारी सुरक्षित राख्नुहोला।"</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"रेकर्ड गर्न थाल्नुहोस्"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"अडियो रेकर्ड गरियोस्"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"डिभाइसको अडियो"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"तपाईंको डिभाइसका सङ्गीत, कल र रिङटोन जस्ता साउन्ड"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"यो कार्य गर्ने सेवाले तपाईंको स्क्रिनमा देख्न सकिने सबै जानकारी अथवा रेकर्ड वा कास्ट गर्दा तपाईंको डिभाइसबाट प्ले गरिएका कुरा हेर्न तथा प्रयोग गर्न सक्छ। यसले हेर्न तथा प्रयोग गर्न सक्ने कुरामा पासवर्ड, भुक्तानीका विवरण, फोटो, सन्देश र तपाईंले प्ले गर्ने अडियो कुराहरू समावेश हुन सक्छन्।"</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"रेकर्ड गर्न वा cast गर्न थाल्ने हो?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> मार्फत रेकर्ड गर्न वा cast गर्न थाल्ने हो?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> लाई सेयर गर्न वा रेकर्ड गर्न दिने हो?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"पूर्ण स्क्रिन"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"एकल एप"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"तपाईंले सेयर गर्दा, रेकर्ड गर्दा वा कास्ट गर्दा<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ले तपाईंको स्क्रिनमा देखिने वा डिभाइसमा प्ले गरिएका सबै कुरा खिच्न सक्छ। त्यसैले सेयर, रेकर्ड वा कास्ट गर्दा पासवर्ड, भुक्तानीको विवरण, म्यासेज वा अन्य संवेदनशील जानकारी सुरक्षित राख्नुहोला।"</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"तपाईंले सेयर गर्दा, रेकर्ड गर्दा वा कास्ट गर्दा<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ले तपाईंको स्क्रिनमा देखिने वा डिभाइसमा प्ले गरिएका सबै कुरा खिच्न सक्छ। त्यसैले पासवर्ड, भुक्तानीको विवरण, म्यासेज वा अन्य संवेदनशील जानकारी सुरक्षित राख्नुहोला।"</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"जारी राख्नुहोस्"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"सेयर वा रेकर्ड गर्नका लागि एप चयन गर्नुहोस्"</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>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 01d0d9fc2216..04c3774be53a 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ଏକ ସ୍କ୍ରି‍ନ୍‍ ରେକର୍ଡ୍‍ ସେସନ୍‍ ପାଇଁ ଚାଲୁଥିବା ବିଜ୍ଞପ୍ତି"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"ରେକର୍ଡିଂ ଆରମ୍ଭ କରିବେ?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"ରେକର୍ଡିଂ ସମୟରେ, Android ସିଷ୍ଟମ୍ ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଦେଖାଯାଉଥିବା ବା ଆପଣଙ୍କ ଡିଭାଇସରେ ଚାଲୁଥିବା ଯେ କୌଣସି ସମ୍ବେଦନଶୀଳ ସୂଚନାକୁ କ୍ୟାପଚର୍ କରିପାରିବ। ଏଥିରେ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ସୂଚନା, ଫଟୋ, ମେସେଜ ଏବଂ ଅଡିଓ ଅନ୍ତର୍ଭୁକ୍ତ।"</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ ରେକର୍ଡ କର"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"ଏକ ସିଙ୍ଗଲ ଆପ ରେକର୍ଡ କରନ୍ତୁ"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"ଆପଣ ରେକର୍ଡିଂ କରିବା ବେଳେ, ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ଆପଣଙ୍କ ଡିଭାଇସରେ ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ Androidର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ କିମ୍ବା ଅନ୍ୟ ସମ୍ବେଦନଶୀଳ ସୂଚନା ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"ଆପଣ ଏକ ଆପ ରେକର୍ଡିଂ କରିବା ବେଳେ, ସେହି ଆପରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ Androidର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ କିମ୍ବା ଅନ୍ୟ ସମ୍ବେଦନଶୀଳ ସୂଚନା ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"ରେକର୍ଡିଂ ଆରମ୍ଭ କରନ୍ତୁ"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"ଅଡିଓ ରେକର୍ଡ କରନ୍ତୁ"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"ଡିଭାଇସ୍ ଅଡିଓ"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"ଆପଣଙ୍କ ଡିଭାଇସରୁ ସାଉଣ୍ଡ, ଯେପରିକି ସଙ୍ଗୀତ, କଲ୍ ଏବଂ ରିଂଟୋନଗୁଡ଼ିକ"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"ସେୟାର କିମ୍ବା ରେକର୍ଡ କରିବା ପାଇଁ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"ଏକ ସିଙ୍ଗଲ ଆପ"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"ଆପଣ ସେୟାର, ରେକର୍ଡ କିମ୍ବା କାଷ୍ଟ କରିବା ସମୟରେ, ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ଆପଣଙ୍କ ଡିଭାଇସରେ ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ କିମ୍ବା ଅନ୍ୟ ସମ୍ବେଦନଶୀଳ ସୂଚନା ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"ଆପଣ ସେୟାର, ରେକର୍ଡ କିମ୍ବା କାଷ୍ଟ କରିବା ସମୟରେ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ଆପରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ ସେହି ଆପର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ କିମ୍ବା ଅନ୍ୟ ସମ୍ବେଦନଶୀଳ ସୂଚନା ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"ଜାରି ରଖନ୍ତୁ"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"ଏକ ଆପକୁ ସେୟାର କିମ୍ବା ରେକର୍ଡ କରନ୍ତୁ"</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>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index e9f4cf9862bb..5f9709a9f46a 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ਕਿਸੇ ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ ਸੈਸ਼ਨ ਲਈ ਚੱਲ ਰਹੀ ਸੂਚਨਾ"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"ਕੀ ਰਿਕਾਰਡਿੰਗ ਸ਼ੁਰੂ ਕਰਨੀ ਹੈ?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"ਰਿਕਾਰਡਿੰਗ ਕਰਨ ਵੇਲੇ, Android ਸਿਸਟਮ ਕੋਈ ਵੀ ਅਜਿਹੀ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਕੈਪਚਰ ਕਰ ਸਕਦਾ ਹੈ ਜੋ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖਣਯੋਗ ਹੈ ਜਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਜਾਂਦੀ ਹੈ। ਇਸ ਵਿੱਚ ਪਾਸਵਰਡ, ਭੁਗਤਾਨ ਵੇਰਵੇ, ਫ਼ੋਟੋਆਂ, ਸੁਨੇਹੇ ਅਤੇ ਆਡੀਓ ਸ਼ਾਮਲ ਹਨ।"</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਨੂੰ ਰਿਕਾਰਡ ਕਰੋ"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"ਇਕਹਿਰੀ ਐਪ ਨੂੰ ਰਿਕਾਰਡ ਕਰੋ"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਰਿਕਾਰਡਿੰਗ ਕਰਨ ਵੇਲੇ, Android ਕੋਲ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਸਦੀ ਜਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ ਜਾਂ ਹੋਰ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਸੰਬੰਧੀ ਸਾਵਧਾਨ ਰਹੋ।"</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਰਿਕਾਰਡਿੰਗ ਕਰਨ ਵੇਲੇ, Android ਕੋਲ ਉਸ ਐਪ \'ਤੇ ਦਿਖਾਈ ਗਈ ਜਾਂ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ ਜਾਂ ਹੋਰ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਸੰਬੰਧੀ ਸਾਵਧਾਨ ਰਹੋ।"</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"ਰਿਕਾਰਡਿੰਗ ਸ਼ੁਰੂ ਕਰੋ"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"ਆਡੀਓ ਰਿਕਾਰਡ ਕਰੋ"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"ਡੀਵਾਈਸ ਆਡੀਓ"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਧੁਨੀ, ਜਿਵੇਂ ਕਿ ਸੰਗੀਤ, ਕਾਲਾਂ ਅਤੇ ਰਿੰਗਟੋਨਾਂ"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"ਕੀ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਨੂੰ ਸਾਂਝਾ ਕਰਨ ਜਾਂ ਰਿਕਾਰਡ ਕਰਨ ਲਈ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"ਪੂਰੀ ਸਕ੍ਰੀਨ"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"ਇਕਹਿਰੀ ਐਪ"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਾਂਝਾ ਕਰਨ, ਰਿਕਾਰਡ ਕਰਨ, ਜਾਂ ਕਾਸਟ ਕਰਨ \'ਤੇ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਕੋਲ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਸਦੀ ਜਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ ਜਾਂ ਹੋਰ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਸੰਬੰਧੀ ਸਾਵਧਾਨ ਰਹੋ।"</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਾਂਝਾ ਕਰਨ, ਰਿਕਾਰਡ ਕਰਨ, ਜਾਂ ਕਾਸਟ ਕਰਨ \'ਤੇ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਕੋਲ ਉਸ ਐਪ \'ਤੇ ਦਿਖਾਈ ਗਈ ਜਾਂ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ ਜਾਂ ਹੋਰ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਸੰਬੰਧੀ ਸਾਵਧਾਨ ਰਹੋ।"</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"ਜਾਰੀ ਰੱਖੋ"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"ਐਪ ਨੂੰ ਸਾਂਝਾ ਕਰੋ ਜਾਂ ਰਿਕਾਰਡ ਕਰੋ"</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>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index dad40e10db75..563f8dc89638 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Stałe powiadomienie o sesji rejestrowania zawartości ekranu"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Rozpocząć nagrywanie?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Podczas nagrywania system Android może rejestrować wszelkie informacje poufne wyświetlane na ekranie lub odtwarzane na urządzeniu. Dotyczy to m.in. haseł, szczegółów płatności, zdjęć, wiadomości i odtwarzanych dźwięków."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Nagrywaj cały ekran"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Nagrywaj pojedynczą aplikację"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Podczas nagrywania Android ma dostęp do wszystkiego, co jest widoczne na ekranie lub odtwarzane na urządzeniu. Zachowaj ostrożność w przypadku haseł, danych do płatności, wiadomości i innych informacji poufnych."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Podczas nagrywania treści z aplikacji Android ma dostęp do wszystkiego, co jest w niej wyświetlane lub odtwarzane. Zachowaj ostrożność w przypadku haseł, danych do płatności, wiadomości i innych informacji poufnych."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Zacznij nagrywać"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Nagraj dźwięk"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Dźwięki z urządzenia"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Dźwięki odtwarzane na urządzeniu, na przykład muzyka, połączenia i dzwonki"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Podczas nagrywania i przesyłania usługa udostępniająca tę funkcję będzie miała dostęp do wszystkich informacji widocznych na ekranie lub odtwarzanych na urządzeniu. Dotyczy to m.in. haseł, szczegółów płatności, zdjęć, wiadomości i odtwarzanych dźwięków."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Rozpocząć nagrywanie lub przesyłanie?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Rozpocząć nagrywanie lub przesyłanie za pomocą aplikacji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Zezwolić aplikacji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> na udostępnianie lub nagrywanie?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Cały ekran"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Pojedyncza aplikacja"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Podczas udostępniania, nagrywania lub przesyłania treści aplikacja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ma dostęp do wszystkiego, co jest widoczne na ekranie lub odtwarzane na urządzeniu. Zachowaj ostrożność w przypadku haseł, danych do płatności, wiadomości i innych informacji poufnych."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Podczas udostępniania, nagrywania lub przesyłania treści aplikacja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ma dostęp do wszystkiego, co jest w niej wyświetlane lub odtwarzane. Zachowaj ostrożność w przypadku haseł, danych do płatności, wiadomości i innych informacji poufnych."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Dalej"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Udostępnianie i nagrywanie za pomocą aplikacji"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Usuń wszystkie"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Zarządzaj"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Historia"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 9110aa0117a4..085522ae1412 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação persistente de uma sessão de gravação de ecrã"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Iniciar a gravação?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Enquanto estiver a gravar, o sistema Android pode capturar quaisquer informações confidenciais que estejam visíveis no ecrã ou que sejam reproduzidas no dispositivo. Isto inclui palavras-passe, informações de pagamento, fotos, mensagens e áudio."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Gravar o ecrã inteiro"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Gravar só uma app"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Enquanto está a gravar, o Android tem acesso a tudo o que está visível no seu ecrã ou é reproduzido no seu dispositivo. Por isso, tenha cuidado com palavras-passe, detalhes de pagamento, mensagens ou outras informações confidenciais."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Enquanto está a gravar uma app, o Android tem acesso a tudo o que é apresentado ou reproduzido nessa app. Por isso, tenha cuidado com palavras-passe, detalhes de pagamento, mensagens ou outras informações confidenciais."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Começar gravação"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Gravar áudio"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Áudio do dispositivo"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"O som do dispositivo, como música, chamadas e toques."</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"O serviço que fornece esta função terá acesso a todas as informações que estiverem visíveis no ecrã ou que forem reproduzidas a partir do dispositivo durante a gravação ou transmissão. Isto inclui informações como palavras-passe, detalhes de pagamentos, fotos, mensagens e áudio reproduzido."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Começar a gravar ou a transmitir?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Começar a gravar ou a transmitir com a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Permitir que a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> partilhe ou grave?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Ecrã inteiro"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Só uma app"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Quando está a partilhar, gravar ou transmitir, a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tem acesso a tudo o que está visível no seu ecrã ou é reproduzido no seu dispositivo. Por isso, tenha cuidado com palavras-passe, detalhes de pagamento, mensagens ou outras informações confidenciais."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Quando está a partilhar, gravar ou transmitir uma app, a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tem acesso a tudo o que é apresentado ou reproduzido nessa app. Por isso, tenha cuidado com palavras-passe, detalhes de pagamento, mensagens ou outras informações confidenciais."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continuar"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Partilhe ou grave uma app"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Limpar tudo"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Gerir"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Histórico"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index f82954eb46c1..0db2dd594477 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificare în curs pentru o sesiune de înregistrare a ecranului"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Începi înregistrarea?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"În timpul înregistrării, sistemul Android poate captura informațiile sensibile vizibile pe ecran sau redate pe dispozitiv. Aici sunt incluse parole, informații de plată, fotografii, mesaje și conținut audio."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Înregistrează tot ecranul"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Înregistrează doar o aplicație"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Când înregistrezi, Android are acces la orice este vizibil pe ecran sau se redă pe dispozitiv. Ai grijă cu parolele, detaliile de plată, mesajele sau alte informații sensibile."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Când înregistrezi o aplicație, Android are acces la orice se afișează sau se redă în aplicație. Ai grijă cu parolele, detaliile de plată, mesajele sau alte informații sensibile."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Începe înregistrarea"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Înregistrează audio"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Conținutul audio de la dispozitiv"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sunetul de la dispozitiv, precum muzică, apeluri și tonuri de sonerie"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Serviciul care oferă această funcție va avea acces la toate informațiile vizibile pe ecran sau redate pe dispozitiv în timp ce înregistrezi sau proiectezi. Între aceste informații se numără parole, detalii de plată, fotografii, mesaje și conținutul audio pe care îl redai."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Începi să înregistrezi sau să proiectezi?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Începi să înregistrezi sau să proiectezi cu <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> poate permite accesul sau înregistra?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Tot ecranul"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"O singură aplicație"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Când permiți accesul, înregistrezi sau proiectezi, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> are acces la orice este vizibil pe ecran sau se redă pe dispozitiv. Ai grijă cu parolele, detaliile de plată, mesajele sau alte informații sensibile."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Când permiți accesul, înregistrezi sau proiectezi o aplicație, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> are acces la orice se afișează pe ecran sau se redă în aplicație. Ai grijă cu parolele, detaliile de plată, mesajele sau alte informații sensibile."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continuă"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Permite accesul la o aplicație sau înregistreaz-o"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Șterge toate notificările"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Gestionează"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Istoric"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 84b5061755a5..7dcf873da40e 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущее уведомление для записи видео с экрана"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Начать запись?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"В записи может появиться конфиденциальная информация, которая видна на экране или воспроизводится на устройстве, например пароли, сведения о платежах, фотографии, сообщения и аудиозаписи."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Записывать весь экран"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Записывать окно приложения"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Когда вы записываете видео с экрана, Android получает доступ ко всему, что видно и воспроизводится на экране устройства. Помните об этом, если соберетесь вводить или просматривать пароли, платежные данные, сообщения и другую конфиденциальную информацию."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Когда вы записываете видео с окна приложения, Android получает доступ ко всему, что видно и воспроизводится в приложении. Помните об этом, если соберетесь вводить или просматривать пароли, платежные данные, сообщения и другую конфиденциальную информацию."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Начать запись"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Записывать аудио"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Звук с устройства"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Звук с вашего устройства, например музыка, звонки и рингтоны"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Разрешить приложению \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" демонстрировать экран или записывать видео с него?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Весь экран"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Отдельное приложение"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Когда вы демонстрируете, транслируете экран или записываете видео с него, приложение \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" получает доступ ко всему, что видно и воспроизводится на экране устройства. Помните об этом, если соберетесь вводить или просматривать пароли, платежные данные, сообщения и другую конфиденциальную информацию."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Когда вы демонстрируете, транслируете экран или записываете видео с него, приложение \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" получает доступ ко всему, что видно и воспроизводится на экране устройства. Помните об этом, если соберетесь вводить или просматривать пароли, платежные данные, сообщения и другую конфиденциальную информацию."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Далее"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Демонстрация экрана или запись видео с него"</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>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 1ccdbf36507f..de498cb075c8 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"තිර පටිගත කිරීමේ සැසියක් සඳහා කෙරෙන දැනුම් දීම"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"පටිගත කිරීම ආරම්භ කරන්නද?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"පටිගත කරන අතරතුර, Android පද්ධතියට ඔබේ තිරයේ පෙනෙන හෝ ඔබේ උපාංගයේ වාදනය කරන ඕනෑම සංවේදී තොරතුරක් ග්‍රහණය කර ගැනීමට හැකිය. මෙයට මුරපද, ගෙවීම් තොරතුරු, ඡායාරූප, පණිවිඩ සහ ඕඩියෝ ඇතුළත් වේ."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"සම්පූර්ණ තිරය පටිගත කරන්න"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"තනි යෙදුමක් පටිගත කරන්න"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"ඔබ පටිගත කරන අතරේ, Android හට ඔබේ තිරයේ පෙනෙන හෝ ඔබේ උපාංගයේ වාදනය වන ඕනෑම දෙයකට ප්‍රවේශය ඇත. එබැවින් මුරපද, ගෙවීම් විස්තර, පණිවිඩ හෝ වෙනත් සංවේදී තොරතුරු සමග ප්‍රවේශම් වන්න."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"ඔබ යෙදුමක් පටිගත කරන අතරේ, Android හට එම යෙදුමේ පෙන්වන හෝ වාදනය කරන ඕනෑම දෙයකට ප්‍රවේශය ඇත. එබැවින් මුරපද, ගෙවීම් විස්තර, පණිවිඩ හෝ වෙනත් සංවේදී තොරතුරු සමග ප්‍රවේශම් වන්න."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"පටිගත කිරීම අරඹන්න"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"ඕඩියෝ පටිගත කරන්න"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"උපාංග ඕඩියෝ"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"සංගීතය, ඇමතුම් සහ නාද රිද්ම වැනි ඔබේ උපාංගය වෙතින් ශබ්ද"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> හට බෙදා ගැනීමට හෝ පටිගත කිරීමට ඉඩ දෙන්න ද?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"සම්පූර්ණ තිරය"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"තනි යෙදුමක්"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"ඔබ බෙදා ගන්නා විට, පටිගත කරන විට, හෝ විකාශනය කරන විට, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> හට ඔබේ තිරයේ පෙනෙන හෝ ඔබේ උපාංගයේ වාදනය වන ඕනෑම දෙයකට ප්‍රවේශය ඇත. එබැවින් මුරපද, ගෙවීම් විස්තර, පණිවිඩ හෝ වෙනත් සංවේදී තොරතුරු සමග ප්‍රවේශම් වන්න."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"ඔබ යෙදුමක් බෙදා ගන්නා විට, පටිගත කරන විට හෝ විකාශය කරන විට, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> හට එම යෙදුමේ පෙන්වන හෝ වාදනය කරන ඕනෑම දෙයකට ප්‍රවේශය ඇත. එබැවින් මුරපද, ගෙවීම් විස්තර, පණිවිඩ හෝ වෙනත් සංවේදී තොරතුරු සමග ප්‍රවේශම් වන්න."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"ඉදිරියට යන්න"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"යෙදුමක් බෙදා ගන්න හෝ පටිගත කරන්න"</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>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index dcebddb4d999..c1a83db6752f 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Njoftim i vazhdueshëm për një seancë regjistrimi të ekranit"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Të niset regjistrimi?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Gjatë regjistrimit, sistemi Android mund të regjistrojë çdo informacion delikat që është i dukshëm në ekranin tënd ose që luhet në pajisje. Kjo përfshin fjalëkalimet, informacionin e pagesave, fotografitë, mesazhet dhe audion."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Regjistro të gjithë ekranin"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Regjistro vetëm një aplikacion"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Gjatë regjistrimit, Android ka qasje te çdo gjë e dukshme në ekranin tënd ose që po luhet në pajisjen tënde. Prandaj ki kujdes me fjalëkalimet, detajet e pagesës, mesazhet ose informacione të tjera të ndjeshme."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Gjatë regjistrimit të një aplikacioni, Android ka qasje te çdo gjë e dukshme ose që po luhet në atë aplikacion. Prandaj, ki kujdes me fjalëkalimet, detajet e pagesës, mesazhet ose informacione të tjera të ndjeshme."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Nis regjistrimin"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Regjistro audio"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audioja e pajisjes"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Tingulli nga pajisja, si muzika, telefonatat dhe tonet e ziles"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Shërbimi që e ofron këtë funksion do të ketë qasje te të gjitha informacionet që janë të dukshme në ekran ose që luhen nga pajisja jote gjatë regjistrimit ose transmetimit. Kjo përfshin informacione, si p.sh.: fjalëkalimet, detajet e pagesave, fotografitë, mesazhet dhe audion që luan ti."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Do të fillosh regjistrimin ose transmetimin?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Fillo regjistrimin ose transmetimin me <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Të lejohet <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> të shpërndajë ose regjistrojë?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Ekran i plotë"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Vetëm një aplikacion"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Gjatë shpërndarjes, regjistrimit ose transmetimit, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ka qasje te çdo gjë e dukshme në ekranin tënd ose që po luhet në pajisjen tënde. Prandaj ki kujdes me fjalëkalimet, detajet e pagesës, mesazhet ose informacione të tjera të ndjeshme."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Gjatë shpërndarjes, regjistrimit ose transmetimit të një aplikacioni, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ka qasje te çdo gjë e dukshme në ekranin tënd ose që po luhet në atë aplikacion. Prandaj, ki kujdes me fjalëkalimet, detajet e pagesës, mesazhet ose informacione të tjera të ndjeshme."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Vazhdo"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Shpërndaj ose regjistro një aplikacion"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Pastroji të gjitha"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Menaxho"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Historiku"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 77f0d30b412d..1778b01b2891 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Avisering om att skärminspelning pågår"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Vill du starta inspelningen?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"När du spelar in kan Android-systemet registrera alla känsliga uppgifter som visas på skärmen eller spelas upp på enheten. Detta omfattar lösenord, betalningsuppgifter, foton, meddelanden och ljud."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Spela in hela skärmen"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Spela in en enda app"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"När du spelar in har Android åtkomst till allt som visas på skärmen eller spelas upp på enheten. Så var försiktig med lösenord, betalningsuppgifter, meddelanden och andra känsliga uppgifter."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"När du spelar in en app har Android åtkomst till allt som visas eller spelas upp i appen. Så var försiktig med lösenord, betalningsuppgifter, meddelanden och andra känsliga uppgifter."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Börja spela in"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Spela in ljud"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Ljud på enheten"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Ljud från enheten, till exempel musik, samtal och ringsignaler"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Den tjänst som tillhandahåller funktionen får åtkomst till all information som visas på skärmen eller spelas upp från enheten när du spelar in eller castar. Detta omfattar uppgifter som lösenord, betalningsinformation, foton, meddelanden och ljud som du spelar upp."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Vill du börja spela in eller casta?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Vill du börja spela in eller casta med <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Vill du tillåta att <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> delar eller spelar in?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Hela skärmen"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"En enda app"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"När du delar, spelar in eller castar har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> åtkomst till allt som visas på skärmen eller spelas upp på enheten. Så var försiktig med lösenord, betalningsuppgifter, meddelanden och andra känsliga uppgifter."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"När du delar, spelar in eller castar en app har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> åtkomst till allt som visas eller spelas upp i appen. Så var försiktig med lösenord, betalningsuppgifter, meddelanden och andra känsliga uppgifter."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Fortsätt"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Dela eller spela in en app"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Rensa alla"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Hantera"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Historik"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index c823f04238cb..dbb90b3c6761 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"திரை ரெக்கார்டிங் அமர்விற்கான தொடர் அறிவிப்பு"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"ரெக்கார்டிங்கைத் தொடங்கவா?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"ரெக்கார்டு செய்யும்போது, உங்கள் திரையில் தோன்றக்கூடிய அல்லது சாதனத்தில் பிளே ஆகக்கூடிய பாதுகாக்கப்பட வேண்டிய தகவலை Android சிஸ்டம் படமெடுக்க முடியும். கடவுச்சொற்கள், பேமெண்ட் தகவல், படங்கள், மெசேஜ்கள், ஆடியோ ஆகியவை இதில் அடங்கும்."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"முழு திரையை ரெக்கார்டு செய்தல்"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"ஓர் ஆப்ஸை ரெக்கார்டு செய்தல்"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"நீங்கள் ரெக்கார்டு செய்யும்போது அந்தச் சாதனத்தில் காட்டப்படும் அல்லது பிளே செய்யப்படும் அனைத்தையும் Android அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், பிற பாதுகாக்கப்பட வேண்டிய தகவல்கள் ஆகியவை குறித்து கவனத்துடன் இருங்கள்."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"ஓர் ஆப்ஸை நீங்கள் ரெக்கார்டு செய்யும்போது அந்த ஆப்ஸில் காட்டப்படும் அல்லது பிளே செய்யப்படும் அனைத்தையும் Android அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், பிற பாதுகாக்கப்பட வேண்டிய தகவல்கள் ஆகியவை குறித்து கவனத்துடன் இருங்கள்."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"ரெக்கார்டிங்கைத் தொடங்கு"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"ஆடியோவை ரெக்கார்டு செய்"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"சாதன ஆடியோ"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"இசை, அழைப்புகள், ரிங்டோன்கள் போன்ற உங்கள் சாதனத்திலிருந்து வரும் ஒலி"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"பகிர அல்லது ரெக்கார்டு செய்ய <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ஆப்ஸை அனுமதிக்கலாமா?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"திரை முழுவதும்"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"ஓர் ஆப்ஸ்"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"நீங்கள் பகிரும்போதோ ரெக்கார்டு செய்யும்போதோ அலைபரப்பும்போதோ உங்கள் சாதனத்தில் காட்டப்படும் அல்லது பிளே செய்யப்படும் அனைத்தையும் <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ஆப்ஸால் அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், பிற பாதுகாக்கப்பட வேண்டிய தகவல்கள் ஆகியவை குறித்து கவனத்துடன் இருங்கள்."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"ஓர் ஆப்ஸை நீங்கள் பகிரும்போதோ ரெக்கார்டு செய்யும்போதோ அலைபரப்பும்போதோ அந்த ஆப்ஸில் காட்டப்படும் அல்லது பிளே செய்யப்படும் அனைத்தையும் <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ஆப்ஸால் அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், பிற பாதுகாக்கப்பட வேண்டிய தகவல்கள் ஆகியவை குறித்து கவனத்துடன் இருங்கள்."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"தொடர்க"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"ஆப்ஸைப் பகிர்தல் அல்லது ரெக்கார்டு செய்தல்"</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>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index e911bb2fbb16..a238f3f64300 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekran kaydı oturumu için devam eden bildirim"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Kayıt başlatılsın mı?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Kayıt sırasında Android Sistemi, ekranınızda görünen veya cihazınızda oynatılan hassas bilgileri yakalayabilir. Buna şifreler, ödeme bilgileri, fotoğraflar, mesajlar ve sesler dahildir."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Tüm ekranı kaydedin"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Tek bir uygulamayı kaydedin"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Kayıt özelliğini kullandığınızda Android, ekranınızda görünen veya cihazınızda oynatılan her şeye erişebilir. Dolayısıyla şifreler, ödeme ayrıntıları, mesajlar veya diğer hassas bilgiler konusunda dikkatli olun."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Bir uygulamayı kaydetme özelliğini kullandığınızda Android, söz konusu uygulamada gösterilen veya oynatılan her şeye erişebilir. Dolayısıyla şifreler, ödeme ayrıntıları, mesajlar veya diğer hassas bilgiler konusunda dikkatli olun."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Kaydı başlat"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Ses kaydet"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Cihaz sesi"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Müzik, aramalar, zil sesleri gibi cihazınızdan sesler"</string>
@@ -371,20 +366,13 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Bu işlevi sağlayan hizmet, ekranınızda görünen veya kayıt ya da yayın sırasında cihazınızdan oynatılan tüm bilgilere erişecektir. Bu bilgiler arasında şifreler, ödeme detayları, fotoğraflar, mesajlar ve çaldığınız sesler gibi bilgiler yer alır."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Kayıt veya yayınlama başlatılsın mı?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ile kayıt veya yayınlama başlatılsın mı?"</string>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> uygulamasının paylaşmasına veya kaydetmesine izin verilsin mi?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Tüm ekran"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Tek bir uygulama"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Paylaşım, kayıt ve yayınlama özelliklerini kullandığınızda <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, ekranınızda görünen veya cihazınızda oynatılan her şeye erişebilir. Dolayısıyla şifreler, ödeme ayrıntıları, mesajlar veya diğer hassas bilgiler konusunda dikkatli olun."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Bir uygulamayı paylaşma, kaydetme ve yayınlama özelliklerini kullandığınızda <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, söz konusu uygulamada gösterilen veya oynatılan her şeye erişebilir. Dolayısıyla şifreler, ödeme ayrıntıları, mesajlar veya diğer hassas bilgiler konusunda dikkatli olun."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Devam"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Uygulamayı paylaşın veya kaydedin"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Tümünü temizle"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Yönet"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Geçmiş"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 011c8bc6e901..d3f392ae7a26 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Сповіщення про сеанс запису екрана"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Почати запис?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"Під час запису система Android може фіксувати будь-яку конфіденційну інформацію, яка з\'являється на екрані або відтворюється на пристрої, зокрема паролі, платіжну інформацію, фотографії, повідомлення та звуки."</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Записувати весь екран"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Записувати окремий додаток"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Коли ви записуєте вміст екрана, ОС Android отримує доступ до всього, що відображається на ньому або відтворюється на пристрої. Тому будьте уважні з паролями, повідомленнями, платіжною й іншою конфіденційною інформацією."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Коли ви записуєте додаток, ОС Android отримує доступ до всього, що відображається або відтворюється в цьому додатку. Тому будьте уважні з паролями, повідомленнями, платіжною й іншою конфіденційною інформацією."</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"Почати запис"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Записувати звук"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Звук із пристрою"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Звук із пристрою, зокрема музика, виклики та сигнали дзвінка"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Дозволити додатку <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> показувати або записувати?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Увесь екран"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Окремий додаток"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Коли ви показуєте, записуєте або транслюєте екран, додаток <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> отримує доступ до всього, що відображається на екрані чи відтворюється на пристрої. Тому будьте уважні з паролями, повідомленнями, платіжною й іншою конфіденційною інформацією."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Коли ви показуєте, записуєте або транслюєте додаток, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> отримує доступ до всього, що відображається або відтворюється в цьому додатку. Тому будьте уважні з паролями, повідомленнями, платіжною й іншою конфіденційною інформацією."</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Продовжити"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Показувати або записувати додаток"</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>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 7d0df6c3e3d3..1e71b14ac717 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"اسکرین ریکارڈ سیشن کیلئے جاری اطلاع"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"ریکارڈنگ شروع کریں؟"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"‏ریکارڈ کرنے کے دوران، Android سسٹم آپ کی اسکرین پر نظر آنے والی یا آپ کے آلہ پر چلنے والی کسی بھی حساس معلومات کو کیپچر کر سکتا ہے۔ اس میں پاس ورڈز، ادائیگی کی معلومات، تصاویر، پیغامات اور آڈیو شامل ہیں۔"</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"پوری اسکرین کو ریکارڈ کریں"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"واحد ایپ کو ریکارڈ کریں"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"‏جب آپ ریکارڈنگ کر رہے ہوتے ہیں تو Android کو آپ کی اسکرین پر دکھائی دینے والی یا آپ کے آلے پر چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ اس لیے پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، یا دیگر حساس معلومات کے سلسلے میں محتاط رہیں۔"</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"‏جب آپ کسی ایپ کو ریکارڈ کر رہے ہوتے ہیں تو Android کو اس ایپ پر دکھائی گئی یا چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ اس لیے پاس ورڈز، ادائیگی کی تفصیلات، پیغامات یا دیگر حساس معلومات کے سلسلے میں محتاط رہیں۔"</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"ریکارڈنگ شروع کریں"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"آڈیو ریکارڈ کریں"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"آلہ کا آڈیو"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"آپ کے آلے سے آواز، جیسے موسیقی، کالز اور رِنگ ٹونز"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کو اشتراک یا ریکارڈ کرنے کی اجازت دیں؟"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"پوری اسکرین"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"واحد ایپ"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"جب آپ اشتراک، ریکارڈنگ یا کاسٹ کر رہے ہوتے ہیں تو <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کو آپ کی اسکرین پر دکھائی دینے والی یا آپ کے آلے پر چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ اس لیے پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، یا دیگر حساس معلومات کے سلسلے میں محتاط رہیں۔"</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"جب آپ اشتراک، ریکارڈنگ یا کاسٹ کر رہے ہوتے ہیں تو <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کو آپ کی اسکرین پر دکھائی گئی یا آپ کے آلے پر چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ اس لیے پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، یا دیگر حساس معلومات کے سلسلے میں محتاط رہیں۔"</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"جاری رکھیں"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"ایپ کا اشتراک یا ریکارڈ کریں"</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>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index d881fa20644c..87821bffc087 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -94,16 +94,11 @@
<string name="screenrecord_channel_description" msgid="4147077128486138351">"持续显示屏幕录制会话通知"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"要开始录制吗?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"在录制内容时,Android 系统可以捕捉到您屏幕上显示或设备中播放的敏感信息,其中包括密码、付款信息、照片、消息和音频。"</string>
- <!-- no translation found for screenrecord_option_entire_screen (1732437834603426934) -->
- <skip />
- <!-- no translation found for screenrecord_option_single_app (5954863081500035825) -->
- <skip />
- <!-- no translation found for screenrecord_warning_entire_screen (8141407178104195610) -->
- <skip />
- <!-- no translation found for screenrecord_warning_single_app (7760723997065948283) -->
- <skip />
- <!-- no translation found for screenrecord_start_recording (348286842544768740) -->
- <skip />
+ <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"录制整个屏幕"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"录制单个应用"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"在您进行录制时,Android 可以访问您的屏幕显示或设备播放的所有内容。因此,请注意保护密码、付款信息、消息或其他敏感信息。"</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"在您录制某个应用时,Android 可以访问此应用显示或播放的所有内容。因此,请注意保护密码、付款信息、消息或其他敏感信息。"</string>
+ <string name="screenrecord_start_recording" msgid="348286842544768740">"开始录制"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"录制音频"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"设备音频"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"设备发出的声音,例如音乐、通话和铃声"</string>
@@ -371,20 +366,13 @@
<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>
- <!-- no translation found for media_projection_permission_dialog_title (7130975432309482596) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_entire_screen (392086473225692983) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_option_single_app (1591110238124910521) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_entire_screen (3989078820637452717) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_warning_single_app (1659532781536753059) -->
- <skip />
- <!-- no translation found for media_projection_permission_dialog_continue (1827799658916736006) -->
- <skip />
- <!-- no translation found for media_projection_permission_app_selector_title (894251621057480704) -->
- <skip />
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"允许 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 分享或录制吗?"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"整个屏幕"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"单个应用"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"在您进行分享、录制或投射时,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可以访问您的屏幕显示或设备播放的所有内容。因此,请注意保护密码、付款信息、消息或其他敏感信息。"</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"在您进行分享、录制或投射时,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可以访问通过此应用显示或播放的所有内容。因此,请注意保护密码、付款信息、消息或其他敏感信息。"</string>
+ <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"继续"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"分享或录制应用"</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>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index d934786b4551..c7036192b418 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -96,8 +96,8 @@
<string name="screenrecord_description" msgid="1123231719680353736">"錄影時,Android 系統可擷取螢幕上顯示或裝置播放的任何敏感資料,包括密碼、付款資料、相片、訊息和音訊。"</string>
<string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"錄製整個螢幕畫面"</string>
<string name="screenrecord_option_single_app" msgid="5954863081500035825">"錄製單一應用程式"</string>
- <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"進行錄製時,Android 可以存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他機密資訊。"</string>
- <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"錄製應用程式時,Android 可以存取在該應用程式中顯示或播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他機密資訊。"</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"進行錄製時,Android 可存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他敏感資料。"</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"錄製應用程式時,Android 可存取在該應用程式中顯示或播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他敏感資料。"</string>
<string name="screenrecord_start_recording" msgid="348286842544768740">"開始錄製"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"錄音"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"裝置音訊"</string>
@@ -366,11 +366,11 @@
<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_permission_dialog_title" msgid="7130975432309482596">"允許 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 分享或錄製?"</string>
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"允許 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 分享或錄製嗎?"</string>
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"整個螢幕畫面"</string>
<string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"單一應用程式"</string>
- <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"進行分享、錄製或投放時,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可以存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他機密資訊。"</string>
- <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"進行分享、錄製或投放應用程式時,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可以存取在該應用程式中顯示或播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他機密資訊。"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"進行分享、錄製或投放時,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他敏感資料。"</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"進行分享、錄製或投放時,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他敏感資料。"</string>
<string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"繼續"</string>
<string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"分享或錄製應用程式"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"全部清除"</string>
diff --git a/packages/SystemUI/res/values/bools.xml b/packages/SystemUI/res/values/bools.xml
index c67ac8d34aa6..8221d78fbfd7 100644
--- a/packages/SystemUI/res/values/bools.xml
+++ b/packages/SystemUI/res/values/bools.xml
@@ -18,6 +18,13 @@
<resources>
<!-- Whether to show the user switcher in quick settings when only a single user is present. -->
<bool name="qs_show_user_switcher_for_single_user">false</bool>
+
<!-- Whether to show a custom biometric prompt size-->
<bool name="use_custom_bp_size">false</bool>
+
+ <!-- Whether to enable clipping on Quick Settings -->
+ <bool name="qs_enable_clipping">true</bool>
+
+ <!-- Whether to enable transparent background for notification scrims -->
+ <bool name="notification_scrim_transparent">false</bool>
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index 7c3b5fc52f0a..2d6bef5a6788 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -60,7 +60,7 @@ public class RemoteAnimationTargetCompat {
public static final int ACTIVITY_TYPE_ASSISTANT = WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
public final int activityType;
- public int taskId;
+ public final int taskId;
public final SurfaceControl leash;
public final boolean isTranslucent;
public final Rect clipRect;
@@ -72,7 +72,7 @@ public class RemoteAnimationTargetCompat {
public final Rect startScreenSpaceBounds;
public final boolean isNotInRecents;
public final Rect contentInsets;
- public ActivityManager.RunningTaskInfo taskInfo;
+ public final ActivityManager.RunningTaskInfo taskInfo;
public final boolean allowEnterPip;
public final int rotationChange;
public final int windowType;
@@ -102,7 +102,7 @@ public class RemoteAnimationTargetCompat {
activityType = app.windowConfiguration.getActivityType();
taskInfo = app.taskInfo;
allowEnterPip = app.allowEnterPip;
- rotationChange = 0;
+ rotationChange = app.rotationChange;
mStartLeash = app.startLeash;
windowType = app.windowType;
@@ -131,6 +131,7 @@ public class RemoteAnimationTargetCompat {
isNotInRecents, mStartLeash, startBounds, taskInfo, allowEnterPip, windowType
);
target.setWillShowImeOnTarget(willShowImeOnTarget);
+ target.setRotationChange(rotationChange);
return target;
}
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index 9151238499dc..910955a45f7b 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -23,12 +23,18 @@ import android.content.res.Resources
import android.text.format.DateFormat
import android.util.TypedValue
import android.view.View
+import androidx.annotation.VisibleForTesting
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags.REGION_SAMPLING
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.plugins.ClockController
-import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.shared.regionsampling.RegionSamplingInstance
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
@@ -38,13 +44,20 @@ import java.util.Locale
import java.util.TimeZone
import java.util.concurrent.Executor
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.launch
/**
* Controller for a Clock provided by the registry and used on the keyguard. Instantiated by
* [KeyguardClockSwitchController]. Functionality is forked from [AnimatableClockController].
*/
open class ClockEventController @Inject constructor(
- private val statusBarStateController: StatusBarStateController,
+ private val keyguardInteractor: KeyguardInteractor,
+ private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
private val broadcastDispatcher: BroadcastDispatcher,
private val batteryController: BatteryController,
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
@@ -53,7 +66,7 @@ open class ClockEventController @Inject constructor(
private val context: Context,
@Main private val mainExecutor: Executor,
@Background private val bgExecutor: Executor,
- private val featureFlags: FeatureFlags,
+ private val featureFlags: FeatureFlags
) {
var clock: ClockController? = null
set(value) {
@@ -70,9 +83,9 @@ open class ClockEventController @Inject constructor(
private var isCharging = false
private var dozeAmount = 0f
private var isKeyguardVisible = false
-
- private val regionSamplingEnabled =
- featureFlags.isEnabled(com.android.systemui.flags.Flags.REGION_SAMPLING)
+ private var isRegistered = false
+ private var disposableHandle: DisposableHandle? = null
+ private val regionSamplingEnabled = featureFlags.isEnabled(REGION_SAMPLING)
private fun updateColors() {
if (regionSamplingEnabled && smallRegionSampler != null && largeRegionSampler != null) {
@@ -165,15 +178,6 @@ open class ClockEventController @Inject constructor(
}
}
- private val statusBarStateListener = object : StatusBarStateController.StateListener {
- override fun onDozeAmountChanged(linear: Float, eased: Float) {
- clock?.animations?.doze(linear)
-
- isDozing = linear > dozeAmount
- dozeAmount = linear
- }
- }
-
private val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() {
override fun onKeyguardVisibilityChanged(visible: Boolean) {
isKeyguardVisible = visible
@@ -195,13 +199,11 @@ open class ClockEventController @Inject constructor(
}
}
- init {
- isDozing = statusBarStateController.isDozing
- }
-
- fun registerListeners() {
- dozeAmount = statusBarStateController.dozeAmount
- isDozing = statusBarStateController.isDozing || dozeAmount != 0f
+ fun registerListeners(parent: View) {
+ if (isRegistered) {
+ return
+ }
+ isRegistered = true
broadcastDispatcher.registerReceiver(
localeBroadcastReceiver,
@@ -210,17 +212,28 @@ open class ClockEventController @Inject constructor(
configurationController.addCallback(configListener)
batteryController.addCallback(batteryCallback)
keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
- statusBarStateController.addCallback(statusBarStateListener)
smallRegionSampler?.startRegionSampler()
largeRegionSampler?.startRegionSampler()
+ disposableHandle = parent.repeatWhenAttached {
+ repeatOnLifecycle(Lifecycle.State.STARTED) {
+ listenForDozing(this)
+ listenForDozeAmount(this)
+ listenForDozeAmountTransition(this)
+ }
+ }
}
fun unregisterListeners() {
+ if (!isRegistered) {
+ return
+ }
+ isRegistered = false
+
+ disposableHandle?.dispose()
broadcastDispatcher.unregisterReceiver(localeBroadcastReceiver)
configurationController.removeCallback(configListener)
batteryController.removeCallback(batteryCallback)
keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
- statusBarStateController.removeCallback(statusBarStateListener)
smallRegionSampler?.stopRegionSampler()
largeRegionSampler?.stopRegionSampler()
}
@@ -235,8 +248,39 @@ open class ClockEventController @Inject constructor(
largeRegionSampler?.dump(pw)
}
- companion object {
- private val TAG = ClockEventController::class.simpleName
- private const val FORMAT_NUMBER = 1234567890
+ @VisibleForTesting
+ internal fun listenForDozeAmount(scope: CoroutineScope): Job {
+ return scope.launch {
+ keyguardInteractor.dozeAmount.collect {
+ dozeAmount = it
+ clock?.animations?.doze(dozeAmount)
+ }
+ }
+ }
+
+ @VisibleForTesting
+ internal fun listenForDozeAmountTransition(scope: CoroutineScope): Job {
+ return scope.launch {
+ keyguardTransitionInteractor.aodToLockscreenTransition.collect {
+ // Would eventually run this:
+ // dozeAmount = it.value
+ // clock?.animations?.doze(dozeAmount)
+ }
+ }
+ }
+
+ @VisibleForTesting
+ internal fun listenForDozing(scope: CoroutineScope): Job {
+ return scope.launch {
+ combine (
+ keyguardInteractor.dozeAmount,
+ keyguardInteractor.isDozing,
+ ) { localDozeAmount, localIsDozing ->
+ localDozeAmount > dozeAmount || localIsDozing
+ }
+ .collect { localIsDozing ->
+ isDozing = localIsDozing
+ }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index b450ec35db32..202134b699d7 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -164,7 +164,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
protected void onViewAttached() {
mClockRegistry.registerClockChangeListener(mClockChangedListener);
setClock(mClockRegistry.createCurrentClock());
- mClockEventController.registerListeners();
+ mClockEventController.registerListeners(mView);
mKeyguardClockTopMargin =
mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
index 55eda0a0cb8a..721c0ba4f865 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
@@ -34,13 +34,14 @@ import com.android.systemui.log.SessionTracker
import com.android.systemui.media.RingtonePlayer
import com.android.systemui.media.taptotransfer.MediaTttCommandLineHelper
import com.android.systemui.media.taptotransfer.receiver.MediaTttChipControllerReceiver
-import com.android.systemui.media.taptotransfer.sender.MediaTttChipControllerSender
+import com.android.systemui.media.taptotransfer.sender.MediaTttSenderCoordinator
import com.android.systemui.power.PowerUI
import com.android.systemui.recents.Recents
import com.android.systemui.settings.dagger.MultiUserUtilsModule
import com.android.systemui.shortcut.ShortcutKeyDispatcher
import com.android.systemui.statusbar.notification.InstantAppNotifier
import com.android.systemui.statusbar.phone.KeyguardLiftController
+import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
import com.android.systemui.theme.ThemeOverlayController
import com.android.systemui.toast.ToastUI
import com.android.systemui.usb.StorageNotification
@@ -217,6 +218,12 @@ abstract class SystemUICoreStartableModule {
@ClassKey(KeyguardLiftController::class)
abstract fun bindKeyguardLiftController(sysui: KeyguardLiftController): CoreStartable
+ /** Inject into MediaTttSenderCoordinator. */
+ @Binds
+ @IntoMap
+ @ClassKey(MediaTttSenderCoordinator::class)
+ abstract fun bindMediaTttSenderCoordinator(sysui: MediaTttSenderCoordinator): CoreStartable
+
/** Inject into MediaTttChipControllerReceiver. */
@Binds
@IntoMap
@@ -225,17 +232,15 @@ abstract class SystemUICoreStartableModule {
sysui: MediaTttChipControllerReceiver
): CoreStartable
- /** Inject into MediaTttChipControllerSender. */
- @Binds
- @IntoMap
- @ClassKey(MediaTttChipControllerSender::class)
- abstract fun bindMediaTttChipControllerSender(
- sysui: MediaTttChipControllerSender
- ): CoreStartable
-
/** Inject into MediaTttCommandLineHelper. */
@Binds
@IntoMap
@ClassKey(MediaTttCommandLineHelper::class)
abstract fun bindMediaTttCommandLineHelper(sysui: MediaTttCommandLineHelper): CoreStartable
+
+ /** Inject into ChipbarCoordinator. */
+ @Binds
+ @IntoMap
+ @ClassKey(ChipbarCoordinator::class)
+ abstract fun bindChipbarController(sysui: ChipbarCoordinator): CoreStartable
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index d89451992351..5506f4c4c8ed 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -111,8 +111,8 @@ public class Flags {
* <p>If this is {@code false}, the interactor and repo skip the controller and directly access
* the framework APIs.
*/
- public static final UnreleasedFlag USER_INTERACTOR_AND_REPO_USE_CONTROLLER =
- new UnreleasedFlag(210);
+ public static final ReleasedFlag USER_INTERACTOR_AND_REPO_USE_CONTROLLER =
+ new ReleasedFlag(210);
/**
* Whether `UserSwitcherController` should use the user interactor.
@@ -123,7 +123,7 @@ public class Flags {
* <p>Note: do not set this to true if {@link #USER_INTERACTOR_AND_REPO_USE_CONTROLLER} is
* {@code true} as it would created a cycle between controller -> interactor -> controller.
*/
- public static final ReleasedFlag USER_CONTROLLER_USES_INTERACTOR = new ReleasedFlag(211);
+ public static final UnreleasedFlag USER_CONTROLLER_USES_INTERACTOR = new UnreleasedFlag(211);
/***************************************/
// 300 - power menu
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 56f1ac46a875..56a1f1ae936e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -43,6 +43,7 @@ import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.data.repository.KeyguardRepositoryModule;
+import com.android.systemui.keyguard.domain.interactor.StartKeyguardTransitionModule;
import com.android.systemui.keyguard.domain.quickaffordance.KeyguardQuickAffordanceModule;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.statusbar.NotificationShadeDepthController;
@@ -72,6 +73,7 @@ import dagger.Provides;
FalsingModule.class,
KeyguardQuickAffordanceModule.class,
KeyguardRepositoryModule.class,
+ StartKeyguardTransitionModule.class,
})
public class KeyguardModule {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index 45b668e609ea..b186ae0ceec4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -21,6 +21,7 @@ import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCall
import com.android.systemui.common.shared.model.Position
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.doze.DozeHost
+import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.policy.KeyguardStateController
import javax.inject.Inject
@@ -85,6 +86,9 @@ interface KeyguardRepository {
*/
val dozeAmount: Flow<Float>
+ /** Observable for the [StatusBarState] */
+ val statusBarState: Flow<StatusBarState>
+
/**
* Returns `true` if the keyguard is showing; `false` otherwise.
*
@@ -185,6 +189,24 @@ constructor(
return keyguardStateController.isShowing
}
+ override val statusBarState: Flow<StatusBarState> = conflatedCallbackFlow {
+ val callback =
+ object : StatusBarStateController.StateListener {
+ override fun onStateChanged(state: Int) {
+ trySendWithFailureLogging(statusBarStateIntToObject(state), TAG, "state")
+ }
+ }
+
+ statusBarStateController.addCallback(callback)
+ trySendWithFailureLogging(
+ statusBarStateIntToObject(statusBarStateController.getState()),
+ TAG,
+ "initial state"
+ )
+
+ awaitClose { statusBarStateController.removeCallback(callback) }
+ }
+
override fun setAnimateDozingTransitions(animate: Boolean) {
_animateBottomAreaDozingTransitions.value = animate
}
@@ -197,6 +219,15 @@ constructor(
_clockPosition.value = Position(x, y)
}
+ private fun statusBarStateIntToObject(value: Int): StatusBarState {
+ return when (value) {
+ 0 -> StatusBarState.SHADE
+ 1 -> StatusBarState.KEYGUARD
+ 2 -> StatusBarState.SHADE_LOCKED
+ else -> throw IllegalArgumentException("Invalid StatusBarState value: $value")
+ }
+ }
+
companion object {
private const val TAG = "KeyguardRepositoryImpl"
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
new file mode 100644
index 000000000000..e8532ecfdc37
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
@@ -0,0 +1,169 @@
+/*
+ * 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.keyguard.data.repository
+
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.ValueAnimator
+import android.animation.ValueAnimator.AnimatorUpdateListener
+import android.annotation.FloatRange
+import android.util.Log
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionInfo
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import java.util.UUID
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.filter
+
+@SysUISingleton
+class KeyguardTransitionRepository @Inject constructor() {
+ /*
+ * Each transition between [KeyguardState]s will have an associated Flow.
+ * In order to collect these events, clients should call [transition].
+ */
+ private val _transitions = MutableStateFlow(TransitionStep())
+ val transitions = _transitions.asStateFlow()
+
+ /* Information about the active transition. */
+ private var currentTransitionInfo: TransitionInfo? = null
+ /*
+ * When manual control of the transition is requested, a unique [UUID] is used as the handle
+ * to permit calls to [updateTransition]
+ */
+ private var updateTransitionId: UUID? = null
+
+ /**
+ * Interactors that require information about changes between [KeyguardState]s will call this to
+ * register themselves for flowable [TransitionStep]s when that transition occurs.
+ */
+ fun transition(from: KeyguardState, to: KeyguardState): Flow<TransitionStep> {
+ return transitions.filter { step -> step.from == from && step.to == to }
+ }
+
+ /**
+ * Begin a transition from one state to another. The [info.from] must match
+ * [currentTransitionInfo.to], or the request will be denied. This is enforced to avoid
+ * unplanned transitions.
+ */
+ fun startTransition(info: TransitionInfo): UUID? {
+ if (currentTransitionInfo != null) {
+ // Open questions:
+ // * Queue of transitions? buffer of 1?
+ // * Are transitions cancellable if a new one is triggered?
+ // * What validation does this need to do?
+ Log.wtf(TAG, "Transition still active: $currentTransitionInfo")
+ return null
+ }
+ currentTransitionInfo?.animator?.cancel()
+
+ currentTransitionInfo = info
+ info.animator?.let { animator ->
+ // An animator was provided, so use it to run the transition
+ animator.setFloatValues(0f, 1f)
+ val updateListener =
+ object : AnimatorUpdateListener {
+ override fun onAnimationUpdate(animation: ValueAnimator) {
+ emitTransition(
+ info,
+ (animation.getAnimatedValue() as Float),
+ TransitionState.RUNNING
+ )
+ }
+ }
+ val adapter =
+ object : AnimatorListenerAdapter() {
+ override fun onAnimationStart(animation: Animator) {
+ Log.i(TAG, "Starting transition: $info")
+ emitTransition(info, 0f, TransitionState.STARTED)
+ }
+ override fun onAnimationCancel(animation: Animator) {
+ Log.i(TAG, "Cancelling transition: $info")
+ }
+ override fun onAnimationEnd(animation: Animator) {
+ Log.i(TAG, "Ending transition: $info")
+ emitTransition(info, 1f, TransitionState.FINISHED)
+ animator.removeListener(this)
+ animator.removeUpdateListener(updateListener)
+ }
+ }
+ animator.addListener(adapter)
+ animator.addUpdateListener(updateListener)
+ animator.start()
+ return@startTransition null
+ }
+ ?: run {
+ Log.i(TAG, "Starting transition (manual): $info")
+ emitTransition(info, 0f, TransitionState.STARTED)
+
+ // No animator, so it's manual. Provide a mechanism to callback
+ updateTransitionId = UUID.randomUUID()
+ return@startTransition updateTransitionId
+ }
+ }
+
+ /**
+ * Allows manual control of a transition. When calling [startTransition], the consumer must pass
+ * in a null animator. In return, it will get a unique [UUID] that will be validated to allow
+ * further updates.
+ *
+ * When the transition is over, TransitionState.FINISHED must be passed into the [state]
+ * parameter.
+ */
+ fun updateTransition(
+ transitionId: UUID,
+ @FloatRange(from = 0.0, to = 1.0) value: Float,
+ state: TransitionState
+ ) {
+ if (updateTransitionId != transitionId) {
+ Log.wtf(TAG, "Attempting to update with old/invalid transitionId: $transitionId")
+ return
+ }
+
+ if (currentTransitionInfo == null) {
+ Log.wtf(TAG, "Attempting to update with null 'currentTransitionInfo'")
+ return
+ }
+
+ currentTransitionInfo?.let { info ->
+ if (state == TransitionState.FINISHED) {
+ updateTransitionId = null
+ Log.i(TAG, "Ending transition: $info")
+ }
+
+ emitTransition(info, value, state)
+ }
+ }
+
+ private fun emitTransition(
+ info: TransitionInfo,
+ value: Float,
+ transitionState: TransitionState
+ ) {
+ if (transitionState == TransitionState.FINISHED) {
+ currentTransitionInfo = null
+ }
+ _transitions.value = TransitionStep(info.from, info.to, value, transitionState)
+ }
+
+ companion object {
+ private const val TAG = "KeyguardTransitionRepository"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodLockscreenTransitionInteractor.kt
new file mode 100644
index 000000000000..400376663f1a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodLockscreenTransitionInteractor.kt
@@ -0,0 +1,77 @@
+/*
+ * 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.keyguard.domain.interactor
+
+import android.animation.ValueAnimator
+import com.android.systemui.animation.Interpolators
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.data.repository.KeyguardRepository
+import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionInfo
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.launch
+
+@SysUISingleton
+class AodLockscreenTransitionInteractor
+@Inject
+constructor(
+ @Application private val scope: CoroutineScope,
+ private val keyguardRepository: KeyguardRepository,
+ private val keyguardTransitionRepository: KeyguardTransitionRepository,
+) : TransitionInteractor("AOD<->LOCKSCREEN") {
+
+ override fun start() {
+ scope.launch {
+ keyguardRepository.isDozing.collect { isDozing ->
+ if (isDozing) {
+ keyguardTransitionRepository.startTransition(
+ TransitionInfo(
+ name,
+ KeyguardState.LOCKSCREEN,
+ KeyguardState.AOD,
+ getAnimator(),
+ )
+ )
+ } else {
+ keyguardTransitionRepository.startTransition(
+ TransitionInfo(
+ name,
+ KeyguardState.AOD,
+ KeyguardState.LOCKSCREEN,
+ getAnimator(),
+ )
+ )
+ }
+ }
+ }
+ }
+
+ private fun getAnimator(): ValueAnimator {
+ return ValueAnimator().apply {
+ setInterpolator(Interpolators.LINEAR)
+ setDuration(TRANSITION_DURATION_MS)
+ }
+ }
+
+ companion object {
+ private const val TRANSITION_DURATION_MS = 500L
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index 192919e32cf6..fc2269c6b01c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -38,7 +38,7 @@ constructor(
val dozeAmount: Flow<Float> = repository.dozeAmount
/** Whether the system is in doze mode. */
val isDozing: Flow<Boolean> = repository.isDozing
- /** Whether the keyguard is showing ot not. */
+ /** Whether the keyguard is showing to not. */
val isKeyguardShowing: Flow<Boolean> = repository.isKeyguardShowing
fun isKeyguardShowing(): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
new file mode 100644
index 000000000000..b166681433a8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
@@ -0,0 +1,49 @@
+/*
+ * 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.keyguard.domain.interactor
+
+import android.util.Log
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton
+import java.util.Set
+import javax.inject.Inject
+
+@SysUISingleton
+class KeyguardTransitionCoreStartable
+@Inject
+constructor(
+ private val interactors: Set<TransitionInteractor>,
+) : CoreStartable {
+
+ override fun start() {
+ // By listing the interactors in a when, the compiler will help enforce all classes
+ // extending the sealed class [TransitionInteractor] will be initialized.
+ interactors.forEach {
+ // `when` needs to be an expression in order for the compiler to enforce it being
+ // exhaustive
+ val ret =
+ when (it) {
+ is LockscreenBouncerTransitionInteractor -> Log.d(TAG, "Started $it")
+ is AodLockscreenTransitionInteractor -> Log.d(TAG, "Started $it")
+ }
+ it.start()
+ }
+ }
+
+ companion object {
+ private const val TAG = "KeyguardTransitionCoreStartable"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
new file mode 100644
index 000000000000..59bb22786917
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.keyguard.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
+import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+
+/** Encapsulates business-logic related to the keyguard transitions. */
+@SysUISingleton
+class KeyguardTransitionInteractor
+@Inject
+constructor(
+ repository: KeyguardTransitionRepository,
+) {
+ /** AOD->LOCKSCREEN transition information. */
+ val aodToLockscreenTransition: Flow<TransitionStep> = repository.transition(AOD, LOCKSCREEN)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenBouncerTransitionInteractor.kt
new file mode 100644
index 000000000000..3c2a12e3836a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenBouncerTransitionInteractor.kt
@@ -0,0 +1,98 @@
+/*
+ * 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.keyguard.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.data.repository.KeyguardRepository
+import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.StatusBarState.SHADE_LOCKED
+import com.android.systemui.keyguard.shared.model.TransitionInfo
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.shade.data.repository.ShadeRepository
+import com.android.systemui.util.kotlin.sample
+import java.util.UUID
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.launch
+
+@SysUISingleton
+class LockscreenBouncerTransitionInteractor
+@Inject
+constructor(
+ @Application private val scope: CoroutineScope,
+ private val keyguardRepository: KeyguardRepository,
+ private val shadeRepository: ShadeRepository,
+ private val keyguardTransitionRepository: KeyguardTransitionRepository,
+) : TransitionInteractor("LOCKSCREEN<->BOUNCER") {
+
+ private var transitionId: UUID? = null
+
+ override fun start() {
+ scope.launch {
+ shadeRepository.shadeModel.sample(
+ combine(
+ keyguardTransitionRepository.transitions,
+ keyguardRepository.statusBarState,
+ ) { transitions, statusBarState ->
+ Pair(transitions, statusBarState)
+ }
+ ) { shadeModel, pair ->
+ val (transitions, statusBarState) = pair
+
+ val id = transitionId
+ if (id != null) {
+ // An existing `id` means a transition is started, and calls to
+ // `updateTransition` will control it until FINISHED
+ keyguardTransitionRepository.updateTransition(
+ id,
+ shadeModel.expansionAmount,
+ if (shadeModel.expansionAmount == 0f || shadeModel.expansionAmount == 1f) {
+ transitionId = null
+ TransitionState.FINISHED
+ } else {
+ TransitionState.RUNNING
+ }
+ )
+ } else {
+ // TODO (b/251849525): Remove statusbarstate check when that state is integrated
+ // into KeyguardTransitionRepository
+ val isOnLockscreen =
+ transitions.transitionState == TransitionState.FINISHED &&
+ transitions.to == KeyguardState.LOCKSCREEN
+ if (
+ isOnLockscreen &&
+ shadeModel.isUserDragging &&
+ statusBarState != SHADE_LOCKED
+ ) {
+ transitionId =
+ keyguardTransitionRepository.startTransition(
+ TransitionInfo(
+ ownerName = name,
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.BOUNCER,
+ animator = null,
+ )
+ )
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt
new file mode 100644
index 000000000000..74c542c0043f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt
@@ -0,0 +1,42 @@
+/*
+ * 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.keyguard.domain.interactor
+
+import com.android.systemui.CoreStartable
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
+import dagger.multibindings.IntoSet
+
+@Module
+abstract class StartKeyguardTransitionModule {
+
+ @Binds
+ @IntoMap
+ @ClassKey(KeyguardTransitionCoreStartable::class)
+ abstract fun bind(impl: KeyguardTransitionCoreStartable): CoreStartable
+
+ @Binds
+ @IntoSet
+ abstract fun lockscreenBouncer(
+ impl: LockscreenBouncerTransitionInteractor
+ ): TransitionInteractor
+
+ @Binds
+ @IntoSet
+ abstract fun aodLockscreen(impl: AodLockscreenTransitionInteractor): TransitionInteractor
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt
new file mode 100644
index 000000000000..a2a46d9e3a71
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt
@@ -0,0 +1,32 @@
+/*
+ * 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.keyguard.domain.interactor
+/**
+ * Each TransitionInteractor is responsible for determining under which conditions to notify
+ * [KeyguardTransitionRepository] to signal a transition. When (and if) the transition occurs is
+ * determined by [KeyguardTransitionRepository].
+ *
+ * [name] field should be a unique identifiable string representing this state, used primarily for
+ * logging
+ *
+ * MUST list implementing classes in dagger module [StartKeyguardTransitionModule] and also in the
+ * 'when' clause of [KeyguardTransitionCoreStartable]
+ */
+sealed class TransitionInteractor(val name: String) {
+
+ abstract fun start()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt
new file mode 100644
index 000000000000..f66d5d3650c8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt
@@ -0,0 +1,34 @@
+/*
+ * 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.keyguard.shared.model
+
+/** List of all possible states to transition to/from */
+enum class KeyguardState {
+ /** For initialization only */
+ NONE,
+ /* Always-on Display. The device is in a low-power mode with a minimal UI visible */
+ AOD,
+ /*
+ * The security screen prompt UI, containing PIN, Password, Pattern, and all FPS
+ * (Fingerprint Sensor) variations, for the user to verify their credentials
+ */
+ BOUNCER,
+ /*
+ * Device is actively displaying keyguard UI and is not in low-power mode. Device may be
+ * unlocked if SWIPE security method is used, or if face lockscreen bypass is false.
+ */
+ LOCKSCREEN,
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/StatusBarState.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/StatusBarState.kt
new file mode 100644
index 000000000000..bb953477583d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/StatusBarState.kt
@@ -0,0 +1,23 @@
+/*
+ * 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.keyguard.shared.model
+
+/** See [com.android.systemui.statusbar.StatusBarState] for definitions */
+enum class StatusBarState {
+ SHADE,
+ KEYGUARD,
+ SHADE_LOCKED,
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionInfo.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionInfo.kt
new file mode 100644
index 000000000000..bfccf3fe076c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionInfo.kt
@@ -0,0 +1,35 @@
+/*
+ * 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.keyguard.shared.model
+
+import android.animation.ValueAnimator
+
+/** Tracks who is controlling the current transition, and how to run it. */
+data class TransitionInfo(
+ val ownerName: String,
+ val from: KeyguardState,
+ val to: KeyguardState,
+ val animator: ValueAnimator?, // 'null' animator signal manual control
+) {
+ override fun toString(): String =
+ "TransitionInfo(ownerName=$ownerName, from=$from, to=$to, " +
+ (if (animator != null) {
+ "animated"
+ } else {
+ "manual"
+ }) +
+ ")"
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionState.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionState.kt
new file mode 100644
index 000000000000..d8691c17f53d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionState.kt
@@ -0,0 +1,24 @@
+/*
+ * 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.keyguard.shared.model
+
+/** Possible states for a running transition between [State] */
+enum class TransitionState {
+ NONE,
+ STARTED,
+ RUNNING,
+ FINISHED
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionStep.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionStep.kt
new file mode 100644
index 000000000000..688ec912aac8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionStep.kt
@@ -0,0 +1,24 @@
+/*
+ * 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.keyguard.shared.model
+
+/** This information will flow from the [KeyguardTransitionRepository] to control the UI layer */
+data class TransitionStep(
+ val from: KeyguardState = KeyguardState.NONE,
+ val to: KeyguardState = KeyguardState.NONE,
+ val value: Float = 0f, // constrained [0.0, 1.0]
+ val transitionState: TransitionState = TransitionState.NONE,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index 80bff83d03a0..5977ed06b0f1 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -133,7 +133,7 @@ class MediaCarouselController @Inject constructor(
private val visualStabilityCallback: OnReorderingAllowedListener
private var needsReordering: Boolean = false
private var keysNeedRemoval = mutableSetOf<String>()
- var shouldScrollToActivePlayer: Boolean = false
+ var shouldScrollToKey: Boolean = false
private var isRtl: Boolean = false
set(value) {
if (value != field) {
@@ -436,7 +436,10 @@ class MediaCarouselController @Inject constructor(
return mediaCarousel
}
- private fun reorderAllPlayers(previousVisiblePlayerKey: MediaPlayerData.MediaSortKey?) {
+ private fun reorderAllPlayers(
+ previousVisiblePlayerKey: MediaPlayerData.MediaSortKey?,
+ key: String? = null
+ ) {
mediaContent.removeAllViews()
for (mediaPlayer in MediaPlayerData.players()) {
mediaPlayer.mediaViewHolder?.let {
@@ -446,18 +449,18 @@ class MediaCarouselController @Inject constructor(
}
}
mediaCarouselScrollHandler.onPlayersChanged()
-
+ MediaPlayerData.updateVisibleMediaPlayers()
// Automatically scroll to the active player if needed
- if (shouldScrollToActivePlayer) {
- shouldScrollToActivePlayer = false
- val activeMediaIndex = MediaPlayerData.firstActiveMediaIndex()
- if (activeMediaIndex != -1) {
+ if (shouldScrollToKey) {
+ shouldScrollToKey = false
+ val mediaIndex = key?.let { MediaPlayerData.getMediaPlayerIndex(it) } ?: -1
+ if (mediaIndex != -1) {
previousVisiblePlayerKey?.let {
val previousVisibleIndex = MediaPlayerData.playerKeys()
.indexOfFirst { key -> it == key }
mediaCarouselScrollHandler
- .scrollToPlayer(previousVisibleIndex, activeMediaIndex)
- } ?: mediaCarouselScrollHandler.scrollToPlayer(destIndex = activeMediaIndex)
+ .scrollToPlayer(previousVisibleIndex, mediaIndex)
+ } ?: mediaCarouselScrollHandler.scrollToPlayer(destIndex = mediaIndex)
}
}
}
@@ -471,9 +474,8 @@ class MediaCarouselController @Inject constructor(
): Boolean = traceSection("MediaCarouselController#addOrUpdatePlayer") {
MediaPlayerData.moveIfExists(oldKey, key)
val existingPlayer = MediaPlayerData.getMediaPlayer(key)
- val curVisibleMediaKey = MediaPlayerData.playerKeys()
+ val curVisibleMediaKey = MediaPlayerData.visiblePlayerKeys()
.elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)
- val isCurVisibleMediaPlaying = curVisibleMediaKey?.data?.isPlaying
if (existingPlayer == null) {
val newPlayer = mediaControlPanelFactory.get()
newPlayer.attachPlayer(MediaViewHolder.create(
@@ -488,8 +490,10 @@ class MediaCarouselController @Inject constructor(
key, data, newPlayer, systemClock, isSsReactivated, debugLogger
)
updatePlayerToState(newPlayer, noAnimation = true)
- if (data.active) {
- reorderAllPlayers(curVisibleMediaKey)
+ // Media data added from a recommendation card should starts playing.
+ if ((shouldScrollToKey && data.isPlaying == true) ||
+ (!shouldScrollToKey && data.active)) {
+ reorderAllPlayers(curVisibleMediaKey, key)
} else {
needsReordering = true
}
@@ -498,14 +502,16 @@ class MediaCarouselController @Inject constructor(
MediaPlayerData.addMediaPlayer(
key, data, existingPlayer, systemClock, isSsReactivated, debugLogger
)
- // Check the playing status of both current visible and new media players
- // To make sure we scroll to the active playing media card.
+ val packageName = MediaPlayerData.smartspaceMediaData?.packageName ?: String()
+ // In case of recommendations hits.
+ // Check the playing status of media player and the package name.
+ // To make sure we scroll to the right app's media player.
if (isReorderingAllowed ||
- shouldScrollToActivePlayer &&
+ shouldScrollToKey &&
data.isPlaying == true &&
- isCurVisibleMediaPlaying == false
+ packageName == data.packageName
) {
- reorderAllPlayers(curVisibleMediaKey)
+ reorderAllPlayers(curVisibleMediaKey, key)
} else {
needsReordering = true
}
@@ -534,7 +540,7 @@ class MediaCarouselController @Inject constructor(
val existingSmartspaceMediaKey = MediaPlayerData.smartspaceMediaKey()
existingSmartspaceMediaKey?.let {
- val removedPlayer = MediaPlayerData.removeMediaPlayer(existingSmartspaceMediaKey)
+ val removedPlayer = MediaPlayerData.removeMediaPlayer(existingSmartspaceMediaKey, true)
removedPlayer?.run { debugLogger.logPotentialMemoryLeak(existingSmartspaceMediaKey) }
}
@@ -546,7 +552,7 @@ class MediaCarouselController @Inject constructor(
ViewGroup.LayoutParams.WRAP_CONTENT)
newRecs.recommendationViewHolder?.recommendations?.setLayoutParams(lp)
newRecs.bindRecommendation(data)
- val curVisibleMediaKey = MediaPlayerData.playerKeys()
+ val curVisibleMediaKey = MediaPlayerData.visiblePlayerKeys()
.elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)
MediaPlayerData.addMediaRecommendation(
key, data, newRecs, shouldPrioritize, systemClock, debugLogger
@@ -572,7 +578,10 @@ class MediaCarouselController @Inject constructor(
logger.logRecommendationRemoved(it.packageName, it.instanceId)
}
}
- val removed = MediaPlayerData.removeMediaPlayer(key)
+ val removed = MediaPlayerData.removeMediaPlayer(
+ key,
+ dismissMediaData || dismissRecommendation
+ )
removed?.apply {
mediaCarouselScrollHandler.onPrePlayerRemoved(removed)
mediaContent.removeView(removed.mediaViewHolder?.player)
@@ -835,18 +844,20 @@ class MediaCarouselController @Inject constructor(
fun logSmartspaceImpression(qsExpanded: Boolean) {
val visibleMediaIndex = mediaCarouselScrollHandler.visibleMediaIndex
if (MediaPlayerData.players().size > visibleMediaIndex) {
- val mediaControlPanel = MediaPlayerData.players().elementAt(visibleMediaIndex)
+ val mediaControlPanel = MediaPlayerData.getMediaControlPanel(visibleMediaIndex)
val hasActiveMediaOrRecommendationCard =
MediaPlayerData.hasActiveMediaOrRecommendationCard()
if (!hasActiveMediaOrRecommendationCard && !qsExpanded) {
// Skip logging if on LS or QQS, and there is no active media card
return
}
- logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN
- mediaControlPanel.mSmartspaceId,
- mediaControlPanel.mUid,
- intArrayOf(mediaControlPanel.surfaceForSmartspaceLogging))
- mediaControlPanel.mIsImpressed = true
+ mediaControlPanel?.let {
+ logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN
+ it.mSmartspaceId,
+ it.mUid,
+ intArrayOf(it.surfaceForSmartspaceLogging))
+ it.mIsImpressed = true
+ }
}
}
@@ -885,7 +896,7 @@ class MediaCarouselController @Inject constructor(
return
}
- val mediaControlKey = MediaPlayerData.playerKeys().elementAt(rank)
+ val mediaControlKey = MediaPlayerData.visiblePlayerKeys().elementAt(rank)
// Only log media resume card when Smartspace data is available
if (!mediaControlKey.isSsMediaRec &&
!mediaManager.smartspaceMediaData.isActive &&
@@ -960,7 +971,8 @@ class MediaCarouselController @Inject constructor(
pw.apply {
println("keysNeedRemoval: $keysNeedRemoval")
println("dataKeys: ${MediaPlayerData.dataKeys()}")
- println("playerSortKeys: ${MediaPlayerData.playerKeys()}")
+ println("orderedPlayerSortKeys: ${MediaPlayerData.playerKeys()}")
+ println("visiblePlayerSortKeys: ${MediaPlayerData.visiblePlayerKeys()}")
println("smartspaceMediaData: ${MediaPlayerData.smartspaceMediaData}")
println("shouldPrioritizeSs: ${MediaPlayerData.shouldPrioritizeSs}")
println("current size: $currentCarouselWidth x $currentCarouselHeight")
@@ -1000,6 +1012,7 @@ internal object MediaPlayerData {
data class MediaSortKey(
val isSsMediaRec: Boolean, // Whether the item represents a Smartspace media recommendation.
val data: MediaData,
+ val key: String,
val updateTime: Long = 0,
val isSsReactivated: Boolean = false
)
@@ -1018,6 +1031,8 @@ internal object MediaPlayerData {
private val mediaPlayers = TreeMap<MediaSortKey, MediaControlPanel>(comparator)
private val mediaData: MutableMap<String, MediaSortKey> = mutableMapOf()
+ // A map that tracks order of visible media players before they get reordered.
+ private val visibleMediaPlayers = LinkedHashMap<String, MediaSortKey>()
fun addMediaPlayer(
key: String,
@@ -1032,9 +1047,10 @@ internal object MediaPlayerData {
debugLogger?.logPotentialMemoryLeak(key)
}
val sortKey = MediaSortKey(isSsMediaRec = false,
- data, clock.currentTimeMillis(), isSsReactivated = isSsReactivated)
+ data, key, clock.currentTimeMillis(), isSsReactivated = isSsReactivated)
mediaData.put(key, sortKey)
mediaPlayers.put(sortKey, player)
+ visibleMediaPlayers.put(key, sortKey)
}
fun addMediaRecommendation(
@@ -1050,10 +1066,16 @@ internal object MediaPlayerData {
if (removedPlayer != null && removedPlayer != player) {
debugLogger?.logPotentialMemoryLeak(key)
}
- val sortKey = MediaSortKey(isSsMediaRec = true,
- EMPTY.copy(isPlaying = false), clock.currentTimeMillis(), isSsReactivated = true)
+ val sortKey = MediaSortKey(
+ isSsMediaRec = true,
+ EMPTY.copy(isPlaying = false),
+ key,
+ clock.currentTimeMillis(),
+ isSsReactivated = true
+ )
mediaData.put(key, sortKey)
mediaPlayers.put(sortKey, player)
+ visibleMediaPlayers.put(key, sortKey)
smartspaceMediaData = data
}
@@ -1067,12 +1089,18 @@ internal object MediaPlayerData {
}
mediaData.remove(oldKey)?.let {
+ // MediaPlayer should not be visible
+ // no need to set isDismissed flag.
val removedPlayer = removeMediaPlayer(newKey)
removedPlayer?.run { debugLogger?.logPotentialMemoryLeak(newKey) }
mediaData.put(newKey, it)
}
}
+ fun getMediaControlPanel(visibleIndex: Int): MediaControlPanel? {
+ return mediaPlayers.get(visiblePlayerKeys().elementAt(visibleIndex))
+ }
+
fun getMediaPlayer(key: String): MediaControlPanel? {
return mediaData.get(key)?.let { mediaPlayers.get(it) }
}
@@ -1087,10 +1115,17 @@ internal object MediaPlayerData {
return -1
}
- fun removeMediaPlayer(key: String) = mediaData.remove(key)?.let {
+ /**
+ * Removes media player given the key.
+ * @param isDismissed determines whether the media player is removed from the carousel.
+ */
+ fun removeMediaPlayer(key: String, isDismissed: Boolean = false) = mediaData.remove(key)?.let {
if (it.isSsMediaRec) {
smartspaceMediaData = null
}
+ if (isDismissed) {
+ visibleMediaPlayers.remove(key)
+ }
mediaPlayers.remove(it)
}
@@ -1102,6 +1137,8 @@ internal object MediaPlayerData {
fun playerKeys() = mediaPlayers.keys
+ fun visiblePlayerKeys() = visibleMediaPlayers.values
+
/** Returns the index of the first non-timeout media. */
fun firstActiveMediaIndex(): Int {
mediaPlayers.entries.forEachIndexed { index, e ->
@@ -1126,6 +1163,7 @@ internal object MediaPlayerData {
fun clear() {
mediaData.clear()
mediaPlayers.clear()
+ visibleMediaPlayers.clear()
}
/* Returns true if there is active media player card or recommendation card */
@@ -1140,4 +1178,16 @@ internal object MediaPlayerData {
}
fun isSsReactivated(key: String): Boolean = mediaData.get(key)?.isSsReactivated ?: false
+
+ /**
+ * This method is called when media players are reordered.
+ * To make sure we have the new version of the order of
+ * media players visible to user.
+ */
+ fun updateVisibleMediaPlayers() {
+ visibleMediaPlayers.clear()
+ playerKeys().forEach {
+ visibleMediaPlayers.put(it.key, it)
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index 759795f84963..fba51dda86e0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -1441,7 +1441,7 @@ public class MediaControlPanel {
}
// Automatically scroll to the active player once the media is loaded.
- mMediaCarouselController.setShouldScrollToActivePlayer(true);
+ mMediaCarouselController.setShouldScrollToKey(true);
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 5096a797a32b..896fb4765c57 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -1130,7 +1130,7 @@ class MediaDataManager(
fun onNotificationRemoved(key: String) {
Assert.isMainThread()
val removed = mediaEntries.remove(key)
- if (useMediaResumption && removed?.resumeAction != null && removed?.isLocalSession()) {
+ if (useMediaResumption && removed?.resumeAction != null && removed.isLocalSession()) {
Log.d(TAG, "Not removing $key because resumable")
// Move to resume key (aka package name) if that key doesn't already exist.
val resumeAction = getResumeMediaAction(removed.resumeAction!!)
diff --git a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
index 66c036cee600..a8a84331050d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
@@ -31,9 +31,7 @@ import com.android.systemui.media.nearby.NearbyMediaDevicesManager;
import com.android.systemui.media.taptotransfer.MediaTttCommandLineHelper;
import com.android.systemui.media.taptotransfer.MediaTttFlags;
import com.android.systemui.media.taptotransfer.common.MediaTttLogger;
-import com.android.systemui.media.taptotransfer.receiver.MediaTttChipControllerReceiver;
import com.android.systemui.media.taptotransfer.receiver.MediaTttReceiverLogger;
-import com.android.systemui.media.taptotransfer.sender.MediaTttChipControllerSender;
import com.android.systemui.media.taptotransfer.sender.MediaTttSenderLogger;
import java.util.Optional;
@@ -94,30 +92,6 @@ public interface MediaModule {
return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager);
}
- /** */
- @Provides
- @SysUISingleton
- static Optional<MediaTttChipControllerSender> providesMediaTttChipControllerSender(
- MediaTttFlags mediaTttFlags,
- Lazy<MediaTttChipControllerSender> controllerSenderLazy) {
- if (!mediaTttFlags.isMediaTttEnabled()) {
- return Optional.empty();
- }
- return Optional.of(controllerSenderLazy.get());
- }
-
- /** */
- @Provides
- @SysUISingleton
- static Optional<MediaTttChipControllerReceiver> providesMediaTttChipControllerReceiver(
- MediaTttFlags mediaTttFlags,
- Lazy<MediaTttChipControllerReceiver> controllerReceiverLazy) {
- if (!mediaTttFlags.isMediaTttEnabled()) {
- return Optional.empty();
- }
- return Optional.of(controllerReceiverLazy.get());
- }
-
@Provides
@SysUISingleton
@MediaTttSenderLogger
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/README.md b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/README.md
index 6379960b85e9..b5a0483e0c69 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/README.md
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/README.md
@@ -41,3 +41,5 @@ in the `receiver` package, and code that's shared between them is in the `common
## Testing
If you want to test out the tap-to-transfer chip without using the `@SystemApi`s, you can use adb
commands instead. Refer to `MediaTttCommandLineHelper` for information about adb commands.
+
+TODO(b/245610654): Update this page once the chipbar migration is complete.
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
index 1461293c7a07..089625ca8d9c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
@@ -36,6 +36,7 @@ import com.android.settingslib.Utils
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.media.taptotransfer.MediaTttFlags
import com.android.systemui.media.taptotransfer.common.MediaTttLogger
import com.android.systemui.media.taptotransfer.common.MediaTttUtils
import com.android.systemui.statusbar.CommandQueue
@@ -52,6 +53,8 @@ import javax.inject.Inject
* A controller to display and hide the Media Tap-To-Transfer chip on the **receiving** device.
*
* This chip is shown when a user is transferring media to/from a sending device and this device.
+ *
+ * TODO(b/245610654): Re-name this to be MediaTttReceiverCoordinator.
*/
@SysUISingleton
class MediaTttChipControllerReceiver @Inject constructor(
@@ -64,6 +67,7 @@ class MediaTttChipControllerReceiver @Inject constructor(
configurationController: ConfigurationController,
powerManager: PowerManager,
@Main private val mainHandler: Handler,
+ private val mediaTttFlags: MediaTttFlags,
private val uiEventLogger: MediaTttReceiverUiEventLogger,
private val viewUtil: ViewUtil,
) : TemporaryViewDisplayController<ChipReceiverInfo, MediaTttLogger>(
@@ -118,7 +122,7 @@ class MediaTttChipControllerReceiver @Inject constructor(
uiEventLogger.logReceiverStateChange(chipState)
if (chipState == ChipStateReceiver.FAR_FROM_SENDER) {
- removeView(removalReason = ChipStateReceiver.FAR_FROM_SENDER::class.simpleName!!)
+ removeView(removalReason = ChipStateReceiver.FAR_FROM_SENDER.name)
return
}
if (appIcon == null) {
@@ -138,7 +142,9 @@ class MediaTttChipControllerReceiver @Inject constructor(
}
override fun start() {
- commandQueue.addCallback(commandQueueCallbacks)
+ if (mediaTttFlags.isMediaTttEnabled()) {
+ commandQueue.addCallback(commandQueueCallbacks)
+ }
}
override fun updateView(newInfo: ChipReceiverInfo, currentView: ViewGroup) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
index aae973dcc1c7..c24b0307fcd1 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
@@ -27,6 +27,8 @@ import com.android.internal.statusbar.IUndoMediaTransferCallback
import com.android.systemui.R
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.temporarydisplay.DEFAULT_TIMEOUT_MILLIS
+import com.android.systemui.temporarydisplay.chipbar.ChipSenderInfo
+import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
/**
* A class enumerating all the possible states of the media tap-to-transfer chip on the sender
@@ -105,7 +107,7 @@ enum class ChipStateSender(
transferStatus = TransferStatus.SUCCEEDED,
) {
override fun undoClickListener(
- controllerSender: MediaTttChipControllerSender,
+ chipbarCoordinator: ChipbarCoordinator,
routeInfo: MediaRoute2Info,
undoCallback: IUndoMediaTransferCallback?,
uiEventLogger: MediaTttSenderUiEventLogger,
@@ -123,9 +125,9 @@ enum class ChipStateSender(
undoCallback.onUndoTriggered()
// The external service should eventually send us a TransferToThisDeviceTriggered
// state, but that may take too long to go through the binder and the user may be
- // confused ast o why the UI hasn't changed yet. So, we immediately change the UI
+ // confused as to why the UI hasn't changed yet. So, we immediately change the UI
// here.
- controllerSender.displayView(
+ chipbarCoordinator.displayView(
ChipSenderInfo(
TRANSFER_TO_THIS_DEVICE_TRIGGERED, routeInfo, undoCallback
)
@@ -144,7 +146,7 @@ enum class ChipStateSender(
transferStatus = TransferStatus.SUCCEEDED,
) {
override fun undoClickListener(
- controllerSender: MediaTttChipControllerSender,
+ chipbarCoordinator: ChipbarCoordinator,
routeInfo: MediaRoute2Info,
undoCallback: IUndoMediaTransferCallback?,
uiEventLogger: MediaTttSenderUiEventLogger,
@@ -164,7 +166,7 @@ enum class ChipStateSender(
// state, but that may take too long to go through the binder and the user may be
// confused as to why the UI hasn't changed yet. So, we immediately change the UI
// here.
- controllerSender.displayView(
+ chipbarCoordinator.displayView(
ChipSenderInfo(
TRANSFER_TO_RECEIVER_TRIGGERED, routeInfo, undoCallback
)
@@ -213,13 +215,13 @@ enum class ChipStateSender(
* Returns a click listener for the undo button on the chip. Returns null if this chip state
* doesn't have an undo button.
*
- * @param controllerSender passed as a parameter in case we want to display a new chip state
+ * @param chipbarCoordinator passed as a parameter in case we want to display a new chipbar
* when undo is clicked.
* @param undoCallback if present, the callback that should be called when the user clicks the
* undo button. The undo button will only be shown if this is non-null.
*/
open fun undoClickListener(
- controllerSender: MediaTttChipControllerSender,
+ chipbarCoordinator: ChipbarCoordinator,
routeInfo: MediaRoute2Info,
undoCallback: IUndoMediaTransferCallback?,
uiEventLogger: MediaTttSenderUiEventLogger,
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt
new file mode 100644
index 000000000000..224303ac098c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt
@@ -0,0 +1,113 @@
+/*
+ * 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.media.taptotransfer.sender
+
+import android.app.StatusBarManager
+import android.content.Context
+import android.media.MediaRoute2Info
+import android.util.Log
+import com.android.internal.statusbar.IUndoMediaTransferCallback
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.media.taptotransfer.MediaTttFlags
+import com.android.systemui.media.taptotransfer.common.MediaTttLogger
+import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.temporarydisplay.chipbar.ChipSenderInfo
+import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
+import com.android.systemui.temporarydisplay.chipbar.SENDER_TAG
+import javax.inject.Inject
+
+/**
+ * A coordinator for showing/hiding the Media Tap-To-Transfer UI on the **sending** device. This UI
+ * is shown when a user is transferring media to/from this device and a receiver device.
+ */
+@SysUISingleton
+class MediaTttSenderCoordinator
+@Inject
+constructor(
+ private val chipbarCoordinator: ChipbarCoordinator,
+ private val commandQueue: CommandQueue,
+ private val context: Context,
+ @MediaTttSenderLogger private val logger: MediaTttLogger,
+ private val mediaTttFlags: MediaTttFlags,
+ private val uiEventLogger: MediaTttSenderUiEventLogger,
+) : CoreStartable {
+
+ private var displayedState: ChipStateSender? = null
+
+ private val commandQueueCallbacks =
+ object : CommandQueue.Callbacks {
+ override fun updateMediaTapToTransferSenderDisplay(
+ @StatusBarManager.MediaTransferSenderState displayState: Int,
+ routeInfo: MediaRoute2Info,
+ undoCallback: IUndoMediaTransferCallback?
+ ) {
+ this@MediaTttSenderCoordinator.updateMediaTapToTransferSenderDisplay(
+ displayState,
+ routeInfo,
+ undoCallback
+ )
+ }
+ }
+
+ override fun start() {
+ if (mediaTttFlags.isMediaTttEnabled()) {
+ commandQueue.addCallback(commandQueueCallbacks)
+ }
+ }
+
+ private fun updateMediaTapToTransferSenderDisplay(
+ @StatusBarManager.MediaTransferSenderState displayState: Int,
+ routeInfo: MediaRoute2Info,
+ undoCallback: IUndoMediaTransferCallback?
+ ) {
+ val chipState: ChipStateSender? = ChipStateSender.getSenderStateFromId(displayState)
+ val stateName = chipState?.name ?: "Invalid"
+ logger.logStateChange(stateName, routeInfo.id, routeInfo.clientPackageName)
+
+ if (chipState == null) {
+ Log.e(SENDER_TAG, "Unhandled MediaTransferSenderState $displayState")
+ return
+ }
+ uiEventLogger.logSenderStateChange(chipState)
+
+ if (chipState == ChipStateSender.FAR_FROM_RECEIVER) {
+ // Return early if we're not displaying a chip anyway
+ val currentDisplayedState = displayedState ?: return
+
+ val removalReason = ChipStateSender.FAR_FROM_RECEIVER.name
+ if (
+ currentDisplayedState.transferStatus == TransferStatus.IN_PROGRESS ||
+ currentDisplayedState.transferStatus == TransferStatus.SUCCEEDED
+ ) {
+ // Don't remove the chip if we're in progress or succeeded, since the user should
+ // still be able to see the status of the transfer.
+ logger.logRemovalBypass(
+ removalReason,
+ bypassReason = "transferStatus=${currentDisplayedState.transferStatus.name}"
+ )
+ return
+ }
+
+ displayedState = null
+ chipbarCoordinator.removeView(removalReason)
+ } else {
+ displayedState = chipState
+ chipbarCoordinator.displayView(ChipSenderInfo(chipState, routeInfo, undoCallback))
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 6da8c69c013b..c089511a7ce9 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -679,7 +679,9 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
public void onViewAttached() {
final Display display = mView.getDisplay();
mView.setComponents(mRecentsOptional);
- mView.setComponents(mCentralSurfacesOptionalLazy.get().get().getPanelController());
+ if (mCentralSurfacesOptionalLazy.get().isPresent()) {
+ mView.setComponents(mCentralSurfacesOptionalLazy.get().get().getPanelController());
+ }
mView.setDisabledFlags(mDisabledFlags1, mSysUiFlagsContainer);
mView.setOnVerticalChangedListener(this::onVerticalChanged);
mView.setOnTouchListener(this::onNavigationTouch);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 97024881ca62..403d276f8cbc 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -148,6 +148,7 @@ public class NavigationBarView extends FrameLayout {
private NavigationBarInflaterView mNavigationInflaterView;
private Optional<Recents> mRecentsOptional = Optional.empty();
+ @Nullable
private NotificationPanelViewController mPanelView;
private RotationContextButton mRotationContextButton;
private FloatingRotationButton mFloatingRotationButton;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
index 6424256f36ab..6e927b071727 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
@@ -417,6 +417,7 @@ class BackPanelController private constructor(
stretchEntryBackIndicator(preThresholdStretchProgress(xTranslation))
GestureState.INACTIVE ->
mView.resetStretch()
+ else -> {}
}
// set y translation
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 84d7e65d289b..27d9da6c2e1e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -25,6 +25,7 @@ import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Pair;
import android.view.DisplayCutout;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
@@ -231,6 +232,16 @@ public class QuickStatusBarHeader extends FrameLayout {
}
}
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ // If using combined headers, only react to touches inside QuickQSPanel
+ if (!mUseCombinedQSHeader || event.getY() > mHeaderQsPanel.getTop()) {
+ return super.onTouchEvent(event);
+ } else {
+ return false;
+ }
+ }
+
void updateResources() {
Resources resources = mContext.getResources();
boolean largeScreenHeaderActive =
diff --git a/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
index d3ed47407b9d..a494f42985ac 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
@@ -280,6 +280,9 @@ class LargeScreenShadeHeaderController @Inject constructor(
context.getString(com.android.internal.R.string.status_bar_alarm_clock)
)
}
+ if (combinedHeaders) {
+ privacyIconsController.onParentVisible()
+ }
}
override fun onViewAttached() {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index a49b7f03acc6..20f0655aa06a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -689,6 +689,7 @@ public final class NotificationPanelViewController {
private int mScreenCornerRadius;
private boolean mQSAnimatingHiddenFromCollapsed;
private boolean mUseLargeScreenShadeHeader;
+ private boolean mEnableQsClipping;
private int mQsClipTop;
private int mQsClipBottom;
@@ -1298,6 +1299,8 @@ public final class NotificationPanelViewController {
mSplitShadeFullTransitionDistance =
mResources.getDimensionPixelSize(R.dimen.split_shade_full_transition_distance);
+
+ mEnableQsClipping = mResources.getBoolean(R.bool.qs_enable_clipping);
}
private void onSplitShadeEnabledChanged() {
@@ -2952,8 +2955,10 @@ public final class NotificationPanelViewController {
mQsTranslationForFullShadeTransition = qsTranslation;
updateQsFrameTranslation();
float currentTranslation = mQsFrame.getTranslationY();
- mQsClipTop = (int) (top - currentTranslation - mQsFrame.getTop());
- mQsClipBottom = (int) (bottom - currentTranslation - mQsFrame.getTop());
+ mQsClipTop = mEnableQsClipping
+ ? (int) (top - currentTranslation - mQsFrame.getTop()) : 0;
+ mQsClipBottom = mEnableQsClipping
+ ? (int) (bottom - currentTranslation - mQsFrame.getTop()) : 0;
mQsVisible = qsVisible;
mQs.setQsVisible(mQsVisible);
mQs.setFancyClipping(
diff --git a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
new file mode 100644
index 000000000000..09019a69df47
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.systemui.shade.data.repository
+
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.shade.ShadeExpansionChangeEvent
+import com.android.systemui.shade.ShadeExpansionListener
+import com.android.systemui.shade.ShadeExpansionStateManager
+import com.android.systemui.shade.domain.model.ShadeModel
+import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.distinctUntilChanged
+
+/** Business logic for shade interactions */
+@SysUISingleton
+class ShadeRepository @Inject constructor(shadeExpansionStateManager: ShadeExpansionStateManager) {
+
+ val shadeModel: Flow<ShadeModel> =
+ conflatedCallbackFlow {
+ val callback =
+ object : ShadeExpansionListener {
+ override fun onPanelExpansionChanged(event: ShadeExpansionChangeEvent) {
+ // Don't propagate ShadeExpansionChangeEvent.dragDownPxAmount field.
+ // It is too noisy and produces extra events that consumers won't care
+ // about
+ val info =
+ ShadeModel(
+ expansionAmount = event.fraction,
+ isExpanded = event.expanded,
+ isUserDragging = event.tracking
+ )
+ trySendWithFailureLogging(info, TAG, "updated shade expansion info")
+ }
+ }
+
+ shadeExpansionStateManager.addExpansionListener(callback)
+ trySendWithFailureLogging(ShadeModel(), TAG, "initial shade expansion info")
+
+ awaitClose { shadeExpansionStateManager.removeExpansionListener(callback) }
+ }
+ .distinctUntilChanged()
+
+ companion object {
+ private const val TAG = "ShadeRepository"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/model/ShadeModel.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/model/ShadeModel.kt
new file mode 100644
index 000000000000..ce0f4283ff83
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/model/ShadeModel.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.systemui.shade.domain.model
+
+import android.annotation.FloatRange
+
+/** Information about shade (NotificationPanel) expansion */
+data class ShadeModel(
+ /** 0 when collapsed, 1 when fully expanded. */
+ @FloatRange(from = 0.0, to = 1.0) val expansionAmount: Float = 0f,
+ /** Whether the panel should be considered expanded */
+ val isExpanded: Boolean = false,
+ /** Whether the user is actively dragging the panel. */
+ val isUserDragging: Boolean = false,
+)
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 1b006485c83d..087dc71f6cf2 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
@@ -1487,7 +1487,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
l.setAlpha(alpha);
}
if (mChildrenContainer != null) {
- mChildrenContainer.setContentAlpha(alpha);
+ mChildrenContainer.setAlpha(alpha);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 0dda2632db66..7b23a56af836 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -461,20 +461,6 @@ public class NotificationChildrenContainer extends ViewGroup
return mAttachedChildren;
}
- /**
- * Sets the alpha on the content, while leaving the background of the container itself as is.
- *
- * @param alpha alpha value to apply to the content
- */
- public void setContentAlpha(float alpha) {
- for (int i = 0; i < mNotificationHeader.getChildCount(); i++) {
- mNotificationHeader.getChildAt(i).setAlpha(alpha);
- }
- for (ExpandableNotificationRow child : getAttachedChildren()) {
- child.setContentAlpha(alpha);
- }
- }
-
/** To be called any time the rows have been updated */
public void updateExpansionStates() {
if (mChildrenExpanded || mUserLocked) {
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 34935db72467..604e1467f950 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -3323,7 +3323,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
@Override
public boolean onBackPressed() {
if (mStatusBarKeyguardViewManager.canHandleBackPressed()) {
- mStatusBarKeyguardViewManager.onBackPressed(false /* unused */);
+ mStatusBarKeyguardViewManager.onBackPressed();
return true;
}
if (mNotificationPanelViewController.isQsCustomizing()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 9f932238007a..84907686835b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -249,6 +249,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
private Callback mCallback;
private boolean mWallpaperSupportsAmbientMode;
private boolean mScreenOn;
+ private boolean mTransparentScrimBackground;
// Scrim blanking callbacks
private Runnable mPendingFrameCallback;
@@ -341,6 +342,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
mScrimBehind.setDefaultFocusHighlightEnabled(false);
mNotificationsScrim.setDefaultFocusHighlightEnabled(false);
mScrimInFront.setDefaultFocusHighlightEnabled(false);
+ mTransparentScrimBackground = notificationsScrim.getResources()
+ .getBoolean(R.bool.notification_scrim_transparent);
updateScrims();
mKeyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
}
@@ -777,13 +780,16 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
float behindFraction = getInterpolatedFraction();
behindFraction = (float) Math.pow(behindFraction, 0.8f);
if (mClipsQsScrim) {
- mBehindAlpha = 1;
- mNotificationsAlpha = behindFraction * mDefaultScrimAlpha;
+ mBehindAlpha = mTransparentScrimBackground ? 0 : 1;
+ mNotificationsAlpha =
+ mTransparentScrimBackground ? 0 : behindFraction * mDefaultScrimAlpha;
} else {
- mBehindAlpha = behindFraction * mDefaultScrimAlpha;
+ mBehindAlpha =
+ mTransparentScrimBackground ? 0 : behindFraction * mDefaultScrimAlpha;
// Delay fade-in of notification scrim a bit further, to coincide with the
// view fade in. Otherwise the empty panel can be quite jarring.
- mNotificationsAlpha = MathUtils.constrainedMap(0f, 1f, 0.3f, 0.75f,
+ mNotificationsAlpha = mTransparentScrimBackground
+ ? 0 : MathUtils.constrainedMap(0f, 1f, 0.3f, 0.75f,
mPanelExpansionFraction);
}
mBehindTint = mState.getBehindTint();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index ebc79ecde134..3a1c03d72a7e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -203,7 +203,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
if (DEBUG) {
Log.d(TAG, "onBackInvokedCallback() called, invoking onBackPressed()");
}
- onBackPressed(false /* unused */);
+ onBackPressed();
};
private boolean mIsBackCallbackRegistered = false;
@@ -1088,16 +1088,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
/**
* Notifies this manager that the back button has been pressed.
*/
- // TODO(b/244635782): This "accept boolean and ignore it, and always return false" was done
- // to make it possible to check this in *and* allow merging to master,
- // where ArcStatusBarKeyguardViewManager inherits this class, and its
- // build will break if we change this interface.
- // So, overall, while this function refactors the behavior of onBackPressed,
- // (it now handles the back press, and no longer returns *whether* it did so)
- // its interface is not changing right now (but will, in a follow-up CL).
- public boolean onBackPressed(boolean ignored) {
+ public void onBackPressed() {
if (!canHandleBackPressed()) {
- return false;
+ return;
}
mCentralSurfaces.endAffordanceLaunch();
@@ -1118,7 +1111,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mNotificationPanelViewController.expandWithoutQs();
}
}
- return false;
+ return;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
index 5cbdf7c43a12..d5d904c50f20 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
@@ -131,7 +131,7 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora
)
cancelViewTimeout?.run()
cancelViewTimeout = mainExecutor.executeDelayed(
- { removeView(TemporaryDisplayRemovalReason.REASON_TIMEOUT) },
+ { removeView(REMOVAL_REASON_TIMEOUT) },
timeout.toLong()
)
}
@@ -175,9 +175,6 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora
*/
fun removeView(removalReason: String) {
val currentDisplayInfo = displayInfo ?: return
- if (shouldIgnoreViewRemoval(currentDisplayInfo.info, removalReason)) {
- return
- }
val currentView = currentDisplayInfo.view
animateViewOut(currentView) { windowManager.removeView(currentView) }
@@ -193,13 +190,6 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora
}
/**
- * Returns true if a view removal request should be ignored and false otherwise.
- *
- * Allows subclasses to keep the view visible for longer in certain circumstances.
- */
- open fun shouldIgnoreViewRemoval(info: T, removalReason: String): Boolean = false
-
- /**
* A method implemented by subclasses to update [currentView] based on [newInfo].
*/
abstract fun updateView(newInfo: T, currentView: ViewGroup)
@@ -236,10 +226,7 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora
)
}
-object TemporaryDisplayRemovalReason {
- const val REASON_TIMEOUT = "TIMEOUT"
- const val REASON_SCREEN_TAP = "SCREEN_TAP"
-}
+private const val REMOVAL_REASON_TIMEOUT = "TIMEOUT"
private data class IconInfo(
val iconName: String,
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt
index ca066f472c0c..1a25e4df3a61 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt
@@ -14,14 +14,12 @@
* limitations under the License.
*/
-package com.android.systemui.media.taptotransfer.sender
+package com.android.systemui.temporarydisplay.chipbar
-import android.app.StatusBarManager
import android.content.Context
import android.graphics.Rect
import android.media.MediaRoute2Info
import android.os.PowerManager
-import android.util.Log
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
@@ -40,10 +38,12 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.media.taptotransfer.common.MediaTttLogger
import com.android.systemui.media.taptotransfer.common.MediaTttUtils
+import com.android.systemui.media.taptotransfer.sender.ChipStateSender
+import com.android.systemui.media.taptotransfer.sender.MediaTttSenderLogger
+import com.android.systemui.media.taptotransfer.sender.MediaTttSenderUiEventLogger
+import com.android.systemui.media.taptotransfer.sender.TransferStatus
import com.android.systemui.plugins.FalsingManager
-import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.temporarydisplay.TemporaryDisplayRemovalReason
import com.android.systemui.temporarydisplay.TemporaryViewDisplayController
import com.android.systemui.temporarydisplay.TemporaryViewInfo
import com.android.systemui.util.concurrency.DelayableExecutor
@@ -51,12 +51,26 @@ import com.android.systemui.util.view.ViewUtil
import javax.inject.Inject
/**
- * A controller to display and hide the Media Tap-To-Transfer chip on the **sending** device. This
- * chip is shown when a user is transferring media to/from this device and a receiver device.
+ * A coordinator for showing/hiding the chipbar.
+ *
+ * The chipbar is a UI element that displays on top of all content. It appears at the top of the
+ * screen and consists of an icon, one line of text, and an optional end icon or action. It will
+ * auto-dismiss after some amount of seconds. The user is *not* able to manually dismiss the
+ * chipbar.
+ *
+ * It should be only be used for critical and temporary information that the user *must* be aware
+ * of. In general, prefer using heads-up notifications, since they are dismissable and will remain
+ * in the list of notifications until the user dismisses them.
+ *
+ * Only one chipbar may be shown at a time.
+ * TODO(b/245610654): Should we just display whichever chipbar was most recently requested, or do we
+ * need to maintain a priority ordering?
+ *
+ * TODO(b/245610654): Remove all media-related items from this class so it's just for generic
+ * chipbars.
*/
@SysUISingleton
-open class MediaTttChipControllerSender @Inject constructor(
- private val commandQueue: CommandQueue,
+open class ChipbarCoordinator @Inject constructor(
context: Context,
@MediaTttSenderLogger logger: MediaTttLogger,
windowManager: WindowManager,
@@ -76,59 +90,25 @@ open class MediaTttChipControllerSender @Inject constructor(
accessibilityManager,
configurationController,
powerManager,
- R.layout.media_ttt_chip,
+ R.layout.chipbar,
MediaTttUtils.WINDOW_TITLE,
MediaTttUtils.WAKE_REASON,
) {
- private lateinit var parent: MediaTttChipRootView
+ private lateinit var parent: ChipbarRootView
override val windowLayoutParams = commonWindowLayoutParams.apply {
gravity = Gravity.TOP.or(Gravity.CENTER_HORIZONTAL)
}
- private val commandQueueCallbacks = object : CommandQueue.Callbacks {
- override fun updateMediaTapToTransferSenderDisplay(
- @StatusBarManager.MediaTransferSenderState displayState: Int,
- routeInfo: MediaRoute2Info,
- undoCallback: IUndoMediaTransferCallback?
- ) {
- this@MediaTttChipControllerSender.updateMediaTapToTransferSenderDisplay(
- displayState, routeInfo, undoCallback
- )
- }
- }
-
- private fun updateMediaTapToTransferSenderDisplay(
- @StatusBarManager.MediaTransferSenderState displayState: Int,
- routeInfo: MediaRoute2Info,
- undoCallback: IUndoMediaTransferCallback?
- ) {
- val chipState: ChipStateSender? = ChipStateSender.getSenderStateFromId(displayState)
- val stateName = chipState?.name ?: "Invalid"
- logger.logStateChange(stateName, routeInfo.id, routeInfo.clientPackageName)
-
- if (chipState == null) {
- Log.e(SENDER_TAG, "Unhandled MediaTransferSenderState $displayState")
- return
- }
- uiEventLogger.logSenderStateChange(chipState)
-
- if (chipState == ChipStateSender.FAR_FROM_RECEIVER) {
- removeView(removalReason = ChipStateSender.FAR_FROM_RECEIVER.name)
- } else {
- displayView(ChipSenderInfo(chipState, routeInfo, undoCallback))
- }
- }
-
- override fun start() {
- commandQueue.addCallback(commandQueueCallbacks)
- }
+ override fun start() {}
override fun updateView(
newInfo: ChipSenderInfo,
currentView: ViewGroup
) {
+ // TODO(b/245610654): Adding logging here.
+
val chipState = newInfo.state
// Detect falsing touches on the chip.
@@ -204,23 +184,6 @@ open class MediaTttChipControllerSender @Inject constructor(
)
}
- override fun shouldIgnoreViewRemoval(info: ChipSenderInfo, removalReason: String): Boolean {
- // Don't remove the chip if we're in progress or succeeded, since the user should still be
- // able to see the status of the transfer. (But do remove it if it's finally timed out.)
- val transferStatus = info.state.transferStatus
- if (
- (transferStatus == TransferStatus.IN_PROGRESS ||
- transferStatus == TransferStatus.SUCCEEDED) &&
- removalReason != TemporaryDisplayRemovalReason.REASON_TIMEOUT
- ) {
- logger.logRemovalBypass(
- removalReason, bypassReason = "transferStatus=${transferStatus.name}"
- )
- return true
- }
- return false
- }
-
override fun getTouchableRegion(view: View, outRect: Rect) {
viewUtil.setRectToViewWindowLocation(view, outRect)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipRootView.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarRootView.kt
index 3373159fba4e..edec420bc408 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipRootView.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarRootView.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.media.taptotransfer.sender
+package com.android.systemui.temporarydisplay.chipbar
import android.content.Context
import android.util.AttributeSet
@@ -22,8 +22,8 @@ import android.view.MotionEvent
import android.widget.FrameLayout
import com.android.systemui.Gefingerpoken
-/** A simple subclass that allows for observing touch events on chip. */
-class MediaTttChipRootView(
+/** A simple subclass that allows for observing touch events on chipbar. */
+class ChipbarRootView(
context: Context,
attrs: AttributeSet?
) : FrameLayout(context, attrs) {
diff --git a/packages/SystemUI/tests/Android.bp b/packages/SystemUI/tests/Android.bp
new file mode 100644
index 000000000000..3c418ed49adc
--- /dev/null
+++ b/packages/SystemUI/tests/Android.bp
@@ -0,0 +1,50 @@
+//
+// 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 {
+ default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+}
+
+android_test {
+ name: "SystemUITests",
+
+ dxflags: ["--multi-dex"],
+ platform_apis: true,
+ test_suites: ["device-tests"],
+ static_libs: ["SystemUI-tests"],
+ compile_multilib: "both",
+
+ jni_libs: [
+ "libdexmakerjvmtiagent",
+ "libmultiplejvmtiagentsinterferenceagent",
+ "libstaticjvmtiagent",
+ ],
+ libs: [
+ "android.test.runner",
+ "telephony-common",
+ "android.test.base",
+ ],
+ aaptflags: [
+ "--extra-packages com.android.systemui",
+ ],
+
+ // sign this with platform cert, so this test is allowed to inject key events into
+ // UI it doesn't own. This is necessary to allow screenshots to be taken
+ certificate: "platform",
+
+ additional_manifests: ["AndroidManifest.xml"],
+ manifest: "AndroidManifest-base.xml",
+}
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
deleted file mode 100644
index ff5165d4e7cf..000000000000
--- a/packages/SystemUI/tests/Android.mk
+++ /dev/null
@@ -1,93 +0,0 @@
-# Copyright (C) 2011 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.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JACK_FLAGS := --multi-dex native
-LOCAL_DX_FLAGS := --multi-dex
-
-LOCAL_PACKAGE_NAME := SystemUITests
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../NOTICE
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
- SystemUI-tests
-
-LOCAL_MULTILIB := both
-
-LOCAL_JNI_SHARED_LIBRARIES := \
- libdexmakerjvmtiagent \
- libmultiplejvmtiagentsinterferenceagent \
- libstaticjvmtiagent
-
-LOCAL_JAVA_LIBRARIES := \
- android.test.runner \
- telephony-common \
- android.test.base \
-
-LOCAL_AAPT_FLAGS := --extra-packages com.android.systemui
-
-# sign this with platform cert, so this test is allowed to inject key events into
-# UI it doesn't own. This is necessary to allow screenshots to be taken
-LOCAL_CERTIFICATE := platform
-
-LOCAL_FULL_LIBS_MANIFEST_FILES := $(LOCAL_PATH)/AndroidManifest.xml
-LOCAL_MANIFEST_FILE := AndroidManifest-base.xml
-
-# Provide jack a list of classes to exclude from code coverage.
-# This is needed because the SystemUITests compile SystemUI source directly, rather than using
-# LOCAL_INSTRUMENTATION_FOR := SystemUI.
-#
-# We want to exclude the test classes from code coverage measurements, but they share the same
-# package as the rest of SystemUI so they can't be easily filtered by package name.
-#
-# Generate a comma separated list of patterns based on the test source files under src/
-# SystemUI classes are in ../src/ so they won't be excluded.
-# Example:
-# Input files: src/com/android/systemui/Test.java src/com/android/systemui/AnotherTest.java
-# Generated exclude list: com.android.systemui.Test*,com.android.systemui.AnotherTest*
-
-# Filter all src files under src/ to just java files
-local_java_files := $(filter %.java,$(call all-java-files-under, src))
-# Transform java file names into full class names.
-# This only works if the class name matches the file name and the directory structure
-# matches the package.
-local_classes := $(subst /,.,$(patsubst src/%.java,%,$(local_java_files)))
-local_comma := ,
-local_empty :=
-local_space := $(local_empty) $(local_empty)
-# Convert class name list to jacoco exclude list
-# This appends a * to all classes and replace the space separators with commas.
-jacoco_exclude := $(subst $(space),$(comma),$(patsubst %,%*,$(local_classes)))
-
-LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.systemui.*,com.android.keyguard.*
-LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := $(jacoco_exclude)
-
-ifeq ($(EXCLUDE_SYSTEMUI_TESTS),)
- include $(BUILD_PACKAGE)
-endif
-
-# Reset variables
-local_java_files :=
-local_classes :=
-local_comma :=
-local_space :=
-jacoco_exclude :=
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index 8a2c35410586..03efd06d0e5e 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -17,17 +17,21 @@ package com.android.keyguard
import android.content.BroadcastReceiver
import android.testing.AndroidTestingRunner
+import android.view.View
import android.widget.TextView
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.plugins.ClockAnimations
import com.android.systemui.plugins.ClockController
import com.android.systemui.plugins.ClockEvents
import com.android.systemui.plugins.ClockFaceController
import com.android.systemui.plugins.ClockFaceEvents
-import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.mockito.any
@@ -37,6 +41,9 @@ import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
import java.util.TimeZone
import java.util.concurrent.Executor
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.yield
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
@@ -57,7 +64,7 @@ import org.mockito.junit.MockitoJUnit
class ClockEventControllerTest : SysuiTestCase() {
@JvmField @Rule val mockito = MockitoJUnit.rule()
- @Mock private lateinit var statusBarStateController: StatusBarStateController
+ @Mock private lateinit var keyguardInteractor: KeyguardInteractor
@Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
@Mock private lateinit var batteryController: BatteryController
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
@@ -72,8 +79,11 @@ class ClockEventControllerTest : SysuiTestCase() {
@Mock private lateinit var largeClockController: ClockFaceController
@Mock private lateinit var smallClockEvents: ClockFaceEvents
@Mock private lateinit var largeClockEvents: ClockFaceEvents
+ @Mock private lateinit var parentView: View
+ @Mock private lateinit var transitionRepository: KeyguardTransitionRepository
+ private lateinit var repository: FakeKeyguardRepository
- private lateinit var clockEventController: ClockEventController
+ private lateinit var underTest: ClockEventController
@Before
fun setUp() {
@@ -86,8 +96,11 @@ class ClockEventControllerTest : SysuiTestCase() {
whenever(clock.events).thenReturn(events)
whenever(clock.animations).thenReturn(animations)
- clockEventController = ClockEventController(
- statusBarStateController,
+ repository = FakeKeyguardRepository()
+
+ underTest = ClockEventController(
+ KeyguardInteractor(repository = repository),
+ KeyguardTransitionInteractor(repository = transitionRepository),
broadcastDispatcher,
batteryController,
keyguardUpdateMonitor,
@@ -98,31 +111,33 @@ class ClockEventControllerTest : SysuiTestCase() {
bgExecutor,
featureFlags
)
+ underTest.clock = clock
+
+ runBlocking(IMMEDIATE) {
+ underTest.registerListeners(parentView)
+
+ repository.setDozing(true)
+ repository.setDozeAmount(1f)
+ }
}
@Test
fun clockSet_validateInitialization() {
- clockEventController.clock = clock
-
verify(clock).initialize(any(), anyFloat(), anyFloat())
}
@Test
fun clockUnset_validateState() {
- clockEventController.clock = clock
- clockEventController.clock = null
+ underTest.clock = null
- assertEquals(clockEventController.clock, null)
+ assertEquals(underTest.clock, null)
}
@Test
- fun themeChanged_verifyClockPaletteUpdated() {
- clockEventController.clock = clock
+ fun themeChanged_verifyClockPaletteUpdated() = runBlocking(IMMEDIATE) {
verify(smallClockEvents).onRegionDarknessChanged(anyBoolean())
verify(largeClockEvents).onRegionDarknessChanged(anyBoolean())
- clockEventController.registerListeners()
-
val captor = argumentCaptor<ConfigurationController.ConfigurationListener>()
verify(configurationController).addCallback(capture(captor))
captor.value.onThemeChanged()
@@ -131,13 +146,10 @@ class ClockEventControllerTest : SysuiTestCase() {
}
@Test
- fun fontChanged_verifyFontSizeUpdated() {
- clockEventController.clock = clock
+ fun fontChanged_verifyFontSizeUpdated() = runBlocking(IMMEDIATE) {
verify(smallClockEvents).onRegionDarknessChanged(anyBoolean())
verify(largeClockEvents).onRegionDarknessChanged(anyBoolean())
- clockEventController.registerListeners()
-
val captor = argumentCaptor<ConfigurationController.ConfigurationListener>()
verify(configurationController).addCallback(capture(captor))
captor.value.onDensityOrFontScaleChanged()
@@ -146,10 +158,7 @@ class ClockEventControllerTest : SysuiTestCase() {
}
@Test
- fun batteryCallback_keyguardShowingCharging_verifyChargeAnimation() {
- clockEventController.clock = clock
- clockEventController.registerListeners()
-
+ fun batteryCallback_keyguardShowingCharging_verifyChargeAnimation() = runBlocking(IMMEDIATE) {
val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
verify(batteryController).addCallback(capture(batteryCaptor))
val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
@@ -161,26 +170,21 @@ class ClockEventControllerTest : SysuiTestCase() {
}
@Test
- fun batteryCallback_keyguardShowingCharging_Duplicate_verifyChargeAnimation() {
- clockEventController.clock = clock
- clockEventController.registerListeners()
-
- val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
- verify(batteryController).addCallback(capture(batteryCaptor))
- val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
- verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor))
- keyguardCaptor.value.onKeyguardVisibilityChanged(true)
- batteryCaptor.value.onBatteryLevelChanged(10, false, true)
- batteryCaptor.value.onBatteryLevelChanged(10, false, true)
-
- verify(animations, times(1)).charge()
- }
+ fun batteryCallback_keyguardShowingCharging_Duplicate_verifyChargeAnimation() =
+ runBlocking(IMMEDIATE) {
+ val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
+ verify(batteryController).addCallback(capture(batteryCaptor))
+ val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
+ verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor))
+ keyguardCaptor.value.onKeyguardVisibilityChanged(true)
+ batteryCaptor.value.onBatteryLevelChanged(10, false, true)
+ batteryCaptor.value.onBatteryLevelChanged(10, false, true)
+
+ verify(animations, times(1)).charge()
+ }
@Test
- fun batteryCallback_keyguardHiddenCharging_verifyChargeAnimation() {
- clockEventController.clock = clock
- clockEventController.registerListeners()
-
+ fun batteryCallback_keyguardHiddenCharging_verifyChargeAnimation() = runBlocking(IMMEDIATE) {
val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
verify(batteryController).addCallback(capture(batteryCaptor))
val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
@@ -192,25 +196,20 @@ class ClockEventControllerTest : SysuiTestCase() {
}
@Test
- fun batteryCallback_keyguardShowingNotCharging_verifyChargeAnimation() {
- clockEventController.clock = clock
- clockEventController.registerListeners()
-
- val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
- verify(batteryController).addCallback(capture(batteryCaptor))
- val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
- verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor))
- keyguardCaptor.value.onKeyguardVisibilityChanged(true)
- batteryCaptor.value.onBatteryLevelChanged(10, false, false)
-
- verify(animations, never()).charge()
- }
+ fun batteryCallback_keyguardShowingNotCharging_verifyChargeAnimation() =
+ runBlocking(IMMEDIATE) {
+ val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
+ verify(batteryController).addCallback(capture(batteryCaptor))
+ val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
+ verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor))
+ keyguardCaptor.value.onKeyguardVisibilityChanged(true)
+ batteryCaptor.value.onBatteryLevelChanged(10, false, false)
+
+ verify(animations, never()).charge()
+ }
@Test
- fun localeCallback_verifyClockNotified() {
- clockEventController.clock = clock
- clockEventController.registerListeners()
-
+ fun localeCallback_verifyClockNotified() = runBlocking(IMMEDIATE) {
val captor = argumentCaptor<BroadcastReceiver>()
verify(broadcastDispatcher).registerReceiver(
capture(captor), any(), eq(null), eq(null), anyInt(), eq(null)
@@ -221,10 +220,7 @@ class ClockEventControllerTest : SysuiTestCase() {
}
@Test
- fun keyguardCallback_visibilityChanged_clockDozeCalled() {
- clockEventController.clock = clock
- clockEventController.registerListeners()
-
+ fun keyguardCallback_visibilityChanged_clockDozeCalled() = runBlocking(IMMEDIATE) {
val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
verify(keyguardUpdateMonitor).registerCallback(capture(captor))
@@ -236,10 +232,7 @@ class ClockEventControllerTest : SysuiTestCase() {
}
@Test
- fun keyguardCallback_timeFormat_clockNotified() {
- clockEventController.clock = clock
- clockEventController.registerListeners()
-
+ fun keyguardCallback_timeFormat_clockNotified() = runBlocking(IMMEDIATE) {
val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
verify(keyguardUpdateMonitor).registerCallback(capture(captor))
captor.value.onTimeFormatChanged("12h")
@@ -248,11 +241,8 @@ class ClockEventControllerTest : SysuiTestCase() {
}
@Test
- fun keyguardCallback_timezoneChanged_clockNotified() {
+ fun keyguardCallback_timezoneChanged_clockNotified() = runBlocking(IMMEDIATE) {
val mockTimeZone = mock<TimeZone>()
- clockEventController.clock = clock
- clockEventController.registerListeners()
-
val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
verify(keyguardUpdateMonitor).registerCallback(capture(captor))
captor.value.onTimeZoneChanged(mockTimeZone)
@@ -261,10 +251,7 @@ class ClockEventControllerTest : SysuiTestCase() {
}
@Test
- fun keyguardCallback_userSwitched_clockNotified() {
- clockEventController.clock = clock
- clockEventController.registerListeners()
-
+ fun keyguardCallback_userSwitched_clockNotified() = runBlocking(IMMEDIATE) {
val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
verify(keyguardUpdateMonitor).registerCallback(capture(captor))
captor.value.onUserSwitchComplete(10)
@@ -273,25 +260,27 @@ class ClockEventControllerTest : SysuiTestCase() {
}
@Test
- fun keyguardCallback_verifyKeyguardChanged() {
- clockEventController.clock = clock
- clockEventController.registerListeners()
+ fun keyguardCallback_verifyKeyguardChanged() = runBlocking(IMMEDIATE) {
+ val job = underTest.listenForDozeAmount(this)
+ repository.setDozeAmount(0.4f)
- val captor = argumentCaptor<StatusBarStateController.StateListener>()
- verify(statusBarStateController).addCallback(capture(captor))
- captor.value.onDozeAmountChanged(0.4f, 0.6f)
+ yield()
verify(animations).doze(0.4f)
+
+ job.cancel()
}
@Test
- fun unregisterListeners_validate() {
- clockEventController.clock = clock
- clockEventController.unregisterListeners()
+ fun unregisterListeners_validate() = runBlocking(IMMEDIATE) {
+ underTest.unregisterListeners()
verify(broadcastDispatcher).unregisterReceiver(any())
verify(configurationController).removeCallback(any())
verify(batteryController).removeCallback(any())
verify(keyguardUpdateMonitor).removeCallback(any())
- verify(statusBarStateController).removeCallback(any())
+ }
+
+ companion object {
+ private val IMMEDIATE = Dispatchers.Main.immediate
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index 400caa3a352a..bb03a47e025c 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -265,6 +265,6 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
private void verifyAttachment(VerificationMode times) {
verify(mClockRegistry, times).registerClockChangeListener(
any(ClockRegistry.ClockChangeListener.class));
- verify(mClockEventController, times).registerListeners();
+ verify(mClockEventController, times).registerListeners(mView);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
new file mode 100644
index 000000000000..1b34100b1cef
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
@@ -0,0 +1,259 @@
+/*
+ * 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.keyguard.data.repository
+
+import android.animation.AnimationHandler.AnimationFrameCallbackProvider
+import android.animation.ValueAnimator
+import android.util.Log
+import android.util.Log.TerribleFailure
+import android.util.Log.TerribleFailureHandler
+import android.view.Choreographer.FrameCallback
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.Interpolators
+import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
+import com.android.systemui.keyguard.shared.model.KeyguardState.BOUNCER
+import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
+import com.android.systemui.keyguard.shared.model.TransitionInfo
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.google.common.truth.Truth.assertThat
+import java.math.BigDecimal
+import java.math.RoundingMode
+import java.util.UUID
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.yield
+import org.junit.After
+import org.junit.Assert.fail
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@SmallTest
+@RunWith(JUnit4::class)
+class KeyguardTransitionRepositoryTest : SysuiTestCase() {
+
+ private lateinit var underTest: KeyguardTransitionRepository
+ private lateinit var oldWtfHandler: TerribleFailureHandler
+ private lateinit var wtfHandler: WtfHandler
+
+ @Before
+ fun setUp() {
+ underTest = KeyguardTransitionRepository()
+ wtfHandler = WtfHandler()
+ oldWtfHandler = Log.setWtfHandler(wtfHandler)
+ }
+
+ @After
+ fun tearDown() {
+ oldWtfHandler?.let { Log.setWtfHandler(it) }
+ }
+
+ @Test
+ fun `startTransition runs animator to completion`() =
+ runBlocking(IMMEDIATE) {
+ val (animator, provider) = setupAnimator(this)
+
+ val steps = mutableListOf<TransitionStep>()
+ val job = underTest.transition(AOD, LOCKSCREEN).onEach { steps.add(it) }.launchIn(this)
+
+ underTest.startTransition(TransitionInfo(OWNER_NAME, AOD, LOCKSCREEN, animator))
+
+ val startTime = System.currentTimeMillis()
+ while (animator.isRunning()) {
+ yield()
+ if (System.currentTimeMillis() - startTime > MAX_TEST_DURATION) {
+ fail("Failed test due to excessive runtime of: $MAX_TEST_DURATION")
+ }
+ }
+
+ assertSteps(steps, listWithStep(BigDecimal(.1)))
+
+ job.cancel()
+ provider.stop()
+ }
+
+ @Test
+ fun `startTransition called during another transition fails`() {
+ underTest.startTransition(TransitionInfo(OWNER_NAME, AOD, LOCKSCREEN, null))
+ underTest.startTransition(TransitionInfo(OWNER_NAME, LOCKSCREEN, BOUNCER, null))
+
+ assertThat(wtfHandler.failed).isTrue()
+ }
+
+ @Test
+ fun `Null animator enables manual control with updateTransition`() =
+ runBlocking(IMMEDIATE) {
+ val steps = mutableListOf<TransitionStep>()
+ val job = underTest.transition(AOD, LOCKSCREEN).onEach { steps.add(it) }.launchIn(this)
+
+ val uuid =
+ underTest.startTransition(
+ TransitionInfo(
+ ownerName = OWNER_NAME,
+ from = AOD,
+ to = LOCKSCREEN,
+ animator = null,
+ )
+ )
+
+ checkNotNull(uuid).let {
+ underTest.updateTransition(it, 0.5f, TransitionState.RUNNING)
+ underTest.updateTransition(it, 1f, TransitionState.FINISHED)
+ }
+
+ assertThat(steps.size).isEqualTo(3)
+ assertThat(steps[0])
+ .isEqualTo(TransitionStep(AOD, LOCKSCREEN, 0f, TransitionState.STARTED))
+ assertThat(steps[1])
+ .isEqualTo(TransitionStep(AOD, LOCKSCREEN, 0.5f, TransitionState.RUNNING))
+ assertThat(steps[2])
+ .isEqualTo(TransitionStep(AOD, LOCKSCREEN, 1f, TransitionState.FINISHED))
+ job.cancel()
+ }
+
+ @Test
+ fun `Attempt to manually update transition with invalid UUID throws exception`() {
+ underTest.updateTransition(UUID.randomUUID(), 0f, TransitionState.RUNNING)
+ assertThat(wtfHandler.failed).isTrue()
+ }
+
+ @Test
+ fun `Attempt to manually update transition after FINISHED state throws exception`() {
+ val uuid =
+ underTest.startTransition(
+ TransitionInfo(
+ ownerName = OWNER_NAME,
+ from = AOD,
+ to = LOCKSCREEN,
+ animator = null,
+ )
+ )
+
+ checkNotNull(uuid).let {
+ underTest.updateTransition(it, 1f, TransitionState.FINISHED)
+ underTest.updateTransition(it, 0.5f, TransitionState.RUNNING)
+ }
+ assertThat(wtfHandler.failed).isTrue()
+ }
+
+ private fun listWithStep(step: BigDecimal): List<BigDecimal> {
+ val steps = mutableListOf<BigDecimal>()
+
+ var i = BigDecimal.ZERO
+ while (i.compareTo(BigDecimal.ONE) <= 0) {
+ steps.add(i)
+ i = (i + step).setScale(2, RoundingMode.HALF_UP)
+ }
+
+ return steps
+ }
+
+ private fun assertSteps(steps: List<TransitionStep>, fractions: List<BigDecimal>) {
+ // + 2 accounts for start and finish of automated transition
+ assertThat(steps.size).isEqualTo(fractions.size + 2)
+
+ assertThat(steps[0]).isEqualTo(TransitionStep(AOD, LOCKSCREEN, 0f, TransitionState.STARTED))
+ fractions.forEachIndexed { index, fraction ->
+ assertThat(steps[index + 1])
+ .isEqualTo(
+ TransitionStep(AOD, LOCKSCREEN, fraction.toFloat(), TransitionState.RUNNING)
+ )
+ }
+ assertThat(steps[steps.size - 1])
+ .isEqualTo(TransitionStep(AOD, LOCKSCREEN, 1f, TransitionState.FINISHED))
+
+ assertThat(wtfHandler.failed).isFalse()
+ }
+
+ private fun setupAnimator(
+ scope: CoroutineScope
+ ): Pair<ValueAnimator, TestFrameCallbackProvider> {
+ val animator =
+ ValueAnimator().apply {
+ setInterpolator(Interpolators.LINEAR)
+ setDuration(ANIMATION_DURATION)
+ }
+
+ val provider = TestFrameCallbackProvider(animator, scope)
+ provider.start()
+
+ return Pair(animator, provider)
+ }
+
+ /** Gives direct control over ValueAnimator. See [AnimationHandler] */
+ private class TestFrameCallbackProvider(
+ private val animator: ValueAnimator,
+ private val scope: CoroutineScope,
+ ) : AnimationFrameCallbackProvider {
+
+ private var frameCount = 1L
+ private var frames = MutableStateFlow(Pair<Long, FrameCallback?>(0L, null))
+ private var job: Job? = null
+
+ fun start() {
+ animator.getAnimationHandler().setProvider(this)
+
+ job =
+ scope.launch {
+ frames.collect {
+ // Delay is required for AnimationHandler to properly register a callback
+ delay(1)
+ val (frameNumber, callback) = it
+ callback?.doFrame(frameNumber)
+ }
+ }
+ }
+
+ fun stop() {
+ job?.cancel()
+ animator.getAnimationHandler().setProvider(null)
+ }
+
+ override fun postFrameCallback(cb: FrameCallback) {
+ frames.value = Pair(++frameCount, cb)
+ }
+ override fun postCommitCallback(runnable: Runnable) {}
+ override fun getFrameTime() = frameCount
+ override fun getFrameDelay() = 1L
+ override fun setFrameDelay(delay: Long) {}
+ }
+
+ private class WtfHandler : TerribleFailureHandler {
+ var failed = false
+ override fun onTerribleFailure(tag: String, what: TerribleFailure, system: Boolean) {
+ failed = true
+ }
+ }
+
+ companion object {
+ private const val MAX_TEST_DURATION = 100L
+ private const val ANIMATION_DURATION = 10L
+ private const val OWNER_NAME = "Test"
+ private val IMMEDIATE = Dispatchers.Main.immediate
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
index cc6874ba3ba7..7e0be6dd1815 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
@@ -76,7 +76,6 @@ class MediaCarouselControllerTest : SysuiTestCase() {
@Mock lateinit var dumpManager: DumpManager
@Mock lateinit var logger: MediaUiEventLogger
@Mock lateinit var debugLogger: MediaCarouselControllerLogger
- @Mock lateinit var mediaPlayer: MediaControlPanel
@Mock lateinit var mediaViewController: MediaViewController
@Mock lateinit var smartspaceMediaData: SmartspaceMediaData
@Captor lateinit var listener: ArgumentCaptor<MediaDataManager.Listener>
@@ -107,8 +106,8 @@ class MediaCarouselControllerTest : SysuiTestCase() {
verify(mediaDataManager).addListener(capture(listener))
verify(visualStabilityProvider)
.addPersistentReorderingAllowedListener(capture(visualStabilityCallback))
- whenever(mediaControlPanelFactory.get()).thenReturn(mediaPlayer)
- whenever(mediaPlayer.mediaViewController).thenReturn(mediaViewController)
+ whenever(mediaControlPanelFactory.get()).thenReturn(panel)
+ whenever(panel.mediaViewController).thenReturn(mediaViewController)
whenever(mediaDataManager.smartspaceMediaData).thenReturn(smartspaceMediaData)
MediaPlayerData.clear()
}
@@ -189,6 +188,10 @@ class MediaCarouselControllerTest : SysuiTestCase() {
for ((index, key) in MediaPlayerData.playerKeys().withIndex()) {
assertEquals(expected.get(index).first, key.data.notificationKey)
}
+
+ for ((index, key) in MediaPlayerData.visiblePlayerKeys().withIndex()) {
+ assertEquals(expected.get(index).first, key.data.notificationKey)
+ }
}
@Test
@@ -204,6 +207,22 @@ class MediaCarouselControllerTest : SysuiTestCase() {
}
@Test
+ fun testOrderWithSmartspace_prioritized_updatingVisibleMediaPlayers() {
+ testPlayerOrdering()
+
+ // If smartspace is prioritized
+ listener.value.onSmartspaceMediaDataLoaded(
+ SMARTSPACE_KEY,
+ EMPTY_SMARTSPACE_MEDIA_DATA.copy(isActive = true),
+ true
+ )
+
+ // Then it should be shown immediately after any actively playing controls
+ assertTrue(MediaPlayerData.playerKeys().elementAt(2).isSsMediaRec)
+ assertTrue(MediaPlayerData.visiblePlayerKeys().elementAt(2).isSsMediaRec)
+ }
+
+ @Test
fun testOrderWithSmartspace_notPrioritized() {
testPlayerOrdering()
@@ -217,6 +236,31 @@ class MediaCarouselControllerTest : SysuiTestCase() {
}
@Test
+ fun testPlayingExistingMediaPlayerFromCarousel_visibleMediaPlayersNotUpdated() {
+ testPlayerOrdering()
+ // playing paused player
+ listener.value.onMediaDataLoaded("paused local",
+ "paused local",
+ DATA.copy(active = true, isPlaying = true,
+ playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false))
+ listener.value.onMediaDataLoaded("playing local",
+ "playing local",
+ DATA.copy(active = true, isPlaying = false,
+ playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = true)
+ )
+
+ assertEquals(
+ MediaPlayerData.getMediaPlayerIndex("paused local"),
+ mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
+ )
+ // paused player order should stays the same in visibleMediaPLayer map.
+ // paused player order should be first in mediaPlayer map.
+ assertEquals(
+ MediaPlayerData.visiblePlayerKeys().elementAt(3),
+ MediaPlayerData.playerKeys().elementAt(0)
+ )
+ }
+ @Test
fun testSwipeDismiss_logged() {
mediaCarouselController.mediaCarouselScrollHandler.dismissCallback.invoke()
@@ -295,7 +339,7 @@ class MediaCarouselControllerTest : SysuiTestCase() {
// adding a media recommendation card.
listener.value.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, EMPTY_SMARTSPACE_MEDIA_DATA,
false)
- mediaCarouselController.shouldScrollToActivePlayer = true
+ mediaCarouselController.shouldScrollToKey = true
// switching between media players.
listener.value.onMediaDataLoaded("playing local",
"playing local",
@@ -315,8 +359,11 @@ class MediaCarouselControllerTest : SysuiTestCase() {
@Test
fun testMediaLoadedFromRecommendationCard_ScrollToActivePlayer() {
- MediaPlayerData.addMediaRecommendation(SMARTSPACE_KEY, EMPTY_SMARTSPACE_MEDIA_DATA, panel,
- false, clock)
+ listener.value.onSmartspaceMediaDataLoaded(
+ SMARTSPACE_KEY,
+ EMPTY_SMARTSPACE_MEDIA_DATA.copy(packageName = "PACKAGE_NAME", isActive = true),
+ false
+ )
listener.value.onMediaDataLoaded("playing local",
null,
DATA.copy(active = true, isPlaying = true,
@@ -332,10 +379,12 @@ class MediaCarouselControllerTest : SysuiTestCase() {
// Replaying the same media player one more time.
// And check that the card stays in its position.
+ mediaCarouselController.shouldScrollToKey = true
listener.value.onMediaDataLoaded("playing local",
null,
DATA.copy(active = true, isPlaying = true,
- playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false)
+ playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false,
+ packageName = "PACKAGE_NAME")
)
playerIndex = MediaPlayerData.getMediaPlayerIndex("playing local")
assertEquals(playerIndex, 0)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
index 3d3ac836d264..83168cb87dfe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
@@ -305,7 +305,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
// Then we save an update with the current time
verify(sharedPrefsEditor).putString(any(), (capture(componentCaptor)))
componentCaptor.value.split(ResumeMediaBrowser.DELIMITER.toRegex())
- ?.dropLastWhile { it.isEmpty() }.forEach {
+ .dropLastWhile { it.isEmpty() }.forEach {
val result = it.split("/")
assertThat(result.size).isEqualTo(3)
assertThat(result[2].toLong()).isEqualTo(currentTime)
@@ -392,7 +392,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
// Then we store the new lastPlayed time
verify(sharedPrefsEditor).putString(any(), (capture(componentCaptor)))
componentCaptor.value.split(ResumeMediaBrowser.DELIMITER.toRegex())
- ?.dropLastWhile { it.isEmpty() }.forEach {
+ .dropLastWhile { it.isEmpty() }.forEach {
val result = it.split("/")
assertThat(result.size).isEqualTo(3)
assertThat(result[2].toLong()).isEqualTo(currentTime)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
index 9577274eef8d..8c3ae3d01f1d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
@@ -34,6 +34,7 @@ import androidx.test.filters.SmallTest
import com.android.internal.logging.testing.UiEventLoggerFake
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.media.taptotransfer.MediaTttFlags
import com.android.systemui.media.taptotransfer.common.MediaTttLogger
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.policy.ConfigurationController
@@ -49,6 +50,7 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Mock
import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
@@ -70,6 +72,8 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() {
@Mock
private lateinit var configurationController: ConfigurationController
@Mock
+ private lateinit var mediaTttFlags: MediaTttFlags
+ @Mock
private lateinit var powerManager: PowerManager
@Mock
private lateinit var viewUtil: ViewUtil
@@ -85,6 +89,7 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() {
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
+ whenever(mediaTttFlags.isMediaTttEnabled()).thenReturn(true)
fakeAppIconDrawable = context.getDrawable(R.drawable.ic_cake)!!
whenever(packageManager.getApplicationIcon(PACKAGE_NAME)).thenReturn(fakeAppIconDrawable)
@@ -107,6 +112,7 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() {
configurationController,
powerManager,
Handler.getMain(),
+ mediaTttFlags,
receiverUiEventLogger,
viewUtil,
)
@@ -118,6 +124,30 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() {
}
@Test
+ fun commandQueueCallback_flagOff_noCallbackAdded() {
+ reset(commandQueue)
+ whenever(mediaTttFlags.isMediaTttEnabled()).thenReturn(false)
+
+ controllerReceiver = MediaTttChipControllerReceiver(
+ commandQueue,
+ context,
+ logger,
+ windowManager,
+ FakeExecutor(FakeSystemClock()),
+ accessibilityManager,
+ configurationController,
+ powerManager,
+ Handler.getMain(),
+ mediaTttFlags,
+ receiverUiEventLogger,
+ viewUtil,
+ )
+ controllerReceiver.start()
+
+ verify(commandQueue, never()).addCallback(any())
+ }
+
+ @Test
fun commandQueueCallback_closeToSender_triggersChip() {
val appName = "FakeAppName"
commandQueueCallback.updateMediaTapToTransferReceiverDisplay(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt
new file mode 100644
index 000000000000..110bbb80df3a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt
@@ -0,0 +1,459 @@
+/*
+ * 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.media.taptotransfer.sender
+
+import android.app.StatusBarManager
+import android.media.MediaRoute2Info
+import android.os.PowerManager
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.View
+import android.view.ViewGroup
+import android.view.WindowManager
+import android.view.accessibility.AccessibilityManager
+import android.widget.TextView
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.testing.UiEventLoggerFake
+import com.android.internal.statusbar.IUndoMediaTransferCallback
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.media.taptotransfer.MediaTttFlags
+import com.android.systemui.media.taptotransfer.common.MediaTttLogger
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.temporarydisplay.chipbar.ChipSenderInfo
+import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
+import com.android.systemui.temporarydisplay.chipbar.FakeChipbarCoordinator
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.time.FakeSystemClock
+import com.android.systemui.util.view.ViewUtil
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class MediaTttSenderCoordinatorTest : SysuiTestCase() {
+ private lateinit var underTest: MediaTttSenderCoordinator
+
+ @Mock private lateinit var accessibilityManager: AccessibilityManager
+ @Mock private lateinit var commandQueue: CommandQueue
+ @Mock private lateinit var configurationController: ConfigurationController
+ @Mock private lateinit var falsingManager: FalsingManager
+ @Mock private lateinit var falsingCollector: FalsingCollector
+ @Mock private lateinit var logger: MediaTttLogger
+ @Mock private lateinit var mediaTttFlags: MediaTttFlags
+ @Mock private lateinit var powerManager: PowerManager
+ @Mock private lateinit var viewUtil: ViewUtil
+ @Mock private lateinit var windowManager: WindowManager
+ private lateinit var chipbarCoordinator: ChipbarCoordinator
+ private lateinit var commandQueueCallback: CommandQueue.Callbacks
+ private lateinit var fakeClock: FakeSystemClock
+ private lateinit var fakeExecutor: FakeExecutor
+ private lateinit var uiEventLoggerFake: UiEventLoggerFake
+ private lateinit var uiEventLogger: MediaTttSenderUiEventLogger
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ whenever(mediaTttFlags.isMediaTttEnabled()).thenReturn(true)
+ whenever(accessibilityManager.getRecommendedTimeoutMillis(any(), any())).thenReturn(TIMEOUT)
+
+ fakeClock = FakeSystemClock()
+ fakeExecutor = FakeExecutor(fakeClock)
+
+ uiEventLoggerFake = UiEventLoggerFake()
+ uiEventLogger = MediaTttSenderUiEventLogger(uiEventLoggerFake)
+
+ chipbarCoordinator =
+ FakeChipbarCoordinator(
+ context,
+ logger,
+ windowManager,
+ fakeExecutor,
+ accessibilityManager,
+ configurationController,
+ powerManager,
+ uiEventLogger,
+ falsingManager,
+ falsingCollector,
+ viewUtil,
+ )
+ chipbarCoordinator.start()
+
+ underTest =
+ MediaTttSenderCoordinator(
+ chipbarCoordinator,
+ commandQueue,
+ context,
+ logger,
+ mediaTttFlags,
+ uiEventLogger,
+ )
+ underTest.start()
+
+ val callbackCaptor = ArgumentCaptor.forClass(CommandQueue.Callbacks::class.java)
+ verify(commandQueue).addCallback(callbackCaptor.capture())
+ commandQueueCallback = callbackCaptor.value!!
+ }
+
+ @Test
+ fun commandQueueCallback_flagOff_noCallbackAdded() {
+ reset(commandQueue)
+ whenever(mediaTttFlags.isMediaTttEnabled()).thenReturn(false)
+ underTest =
+ MediaTttSenderCoordinator(
+ chipbarCoordinator,
+ commandQueue,
+ context,
+ logger,
+ mediaTttFlags,
+ uiEventLogger,
+ )
+ underTest.start()
+
+ verify(commandQueue, never()).addCallback(any())
+ }
+
+ @Test
+ fun commandQueueCallback_almostCloseToStartCast_triggersCorrectChip() {
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
+ routeInfo,
+ null
+ )
+
+ assertThat(getChipView().getChipText())
+ .isEqualTo(almostCloseToStartCast().state.getChipTextString(context, OTHER_DEVICE_NAME))
+ assertThat(uiEventLoggerFake.eventId(0))
+ .isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_ALMOST_CLOSE_TO_START_CAST.id)
+ }
+
+ @Test
+ fun commandQueueCallback_almostCloseToEndCast_triggersCorrectChip() {
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST,
+ routeInfo,
+ null
+ )
+
+ assertThat(getChipView().getChipText())
+ .isEqualTo(almostCloseToEndCast().state.getChipTextString(context, OTHER_DEVICE_NAME))
+ assertThat(uiEventLoggerFake.eventId(0))
+ .isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_ALMOST_CLOSE_TO_END_CAST.id)
+ }
+
+ @Test
+ fun commandQueueCallback_transferToReceiverTriggered_triggersCorrectChip() {
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED,
+ routeInfo,
+ null
+ )
+
+ assertThat(getChipView().getChipText())
+ .isEqualTo(
+ transferToReceiverTriggered().state.getChipTextString(context, OTHER_DEVICE_NAME)
+ )
+ assertThat(uiEventLoggerFake.eventId(0))
+ .isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_TRIGGERED.id)
+ }
+
+ @Test
+ fun commandQueueCallback_transferToThisDeviceTriggered_triggersCorrectChip() {
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
+ routeInfo,
+ null
+ )
+
+ assertThat(getChipView().getChipText())
+ .isEqualTo(
+ transferToThisDeviceTriggered().state.getChipTextString(context, OTHER_DEVICE_NAME)
+ )
+ assertThat(uiEventLoggerFake.eventId(0))
+ .isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_TRIGGERED.id)
+ }
+
+ @Test
+ fun commandQueueCallback_transferToReceiverSucceeded_triggersCorrectChip() {
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
+ routeInfo,
+ null
+ )
+
+ assertThat(getChipView().getChipText())
+ .isEqualTo(
+ transferToReceiverSucceeded().state.getChipTextString(context, OTHER_DEVICE_NAME)
+ )
+ assertThat(uiEventLoggerFake.eventId(0))
+ .isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_SUCCEEDED.id)
+ }
+
+ @Test
+ fun commandQueueCallback_transferToThisDeviceSucceeded_triggersCorrectChip() {
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
+ routeInfo,
+ null
+ )
+
+ assertThat(getChipView().getChipText())
+ .isEqualTo(
+ transferToThisDeviceSucceeded().state.getChipTextString(context, OTHER_DEVICE_NAME)
+ )
+ assertThat(uiEventLoggerFake.eventId(0))
+ .isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_SUCCEEDED.id)
+ }
+
+ @Test
+ fun commandQueueCallback_transferToReceiverFailed_triggersCorrectChip() {
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED,
+ routeInfo,
+ null
+ )
+
+ assertThat(getChipView().getChipText())
+ .isEqualTo(
+ transferToReceiverFailed().state.getChipTextString(context, OTHER_DEVICE_NAME)
+ )
+ assertThat(uiEventLoggerFake.eventId(0))
+ .isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_FAILED.id)
+ }
+
+ @Test
+ fun commandQueueCallback_transferToThisDeviceFailed_triggersCorrectChip() {
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED,
+ routeInfo,
+ null
+ )
+
+ assertThat(getChipView().getChipText())
+ .isEqualTo(
+ transferToThisDeviceFailed().state.getChipTextString(context, OTHER_DEVICE_NAME)
+ )
+ assertThat(uiEventLoggerFake.eventId(0))
+ .isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_FAILED.id)
+ }
+
+ @Test
+ fun commandQueueCallback_farFromReceiver_noChipShown() {
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
+ routeInfo,
+ null
+ )
+
+ verify(windowManager, never()).addView(any(), any())
+ assertThat(uiEventLoggerFake.eventId(0))
+ .isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_FAR_FROM_RECEIVER.id)
+ }
+
+ @Test
+ fun commandQueueCallback_almostCloseThenFarFromReceiver_chipShownThenHidden() {
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
+ routeInfo,
+ null
+ )
+
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
+ routeInfo,
+ null
+ )
+
+ val viewCaptor = ArgumentCaptor.forClass(View::class.java)
+ verify(windowManager).addView(viewCaptor.capture(), any())
+ verify(windowManager).removeView(viewCaptor.value)
+ }
+
+ @Test
+ fun commandQueueCallback_invalidStateParam_noChipShown() {
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(100, routeInfo, null)
+
+ verify(windowManager, never()).addView(any(), any())
+ }
+
+ @Test
+ fun receivesNewStateFromCommandQueue_isLogged() {
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
+ routeInfo,
+ null
+ )
+
+ verify(logger).logStateChange(any(), any(), any())
+ }
+
+ @Test
+ fun transferToReceiverTriggeredThenFarFromReceiver_viewStillDisplayedButStillTimesOut() {
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED,
+ routeInfo,
+ null
+ )
+
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
+ routeInfo,
+ null
+ )
+ fakeExecutor.runAllReady()
+
+ verify(windowManager, never()).removeView(any())
+ verify(logger).logRemovalBypass(any(), any())
+
+ fakeClock.advanceTime(TIMEOUT + 1L)
+
+ verify(windowManager).removeView(any())
+ }
+
+ @Test
+ fun transferToThisDeviceTriggeredThenFarFromReceiver_viewStillDisplayedButDoesTimeOut() {
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
+ routeInfo,
+ null
+ )
+
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
+ routeInfo,
+ null
+ )
+ fakeExecutor.runAllReady()
+
+ verify(windowManager, never()).removeView(any())
+ verify(logger).logRemovalBypass(any(), any())
+
+ fakeClock.advanceTime(TIMEOUT + 1L)
+
+ verify(windowManager).removeView(any())
+ }
+
+ @Test
+ fun transferToReceiverSucceededThenFarFromReceiver_viewStillDisplayedButDoesTimeOut() {
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
+ routeInfo,
+ null
+ )
+
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
+ routeInfo,
+ null
+ )
+ fakeExecutor.runAllReady()
+
+ verify(windowManager, never()).removeView(any())
+ verify(logger).logRemovalBypass(any(), any())
+
+ fakeClock.advanceTime(TIMEOUT + 1L)
+
+ verify(windowManager).removeView(any())
+ }
+
+ @Test
+ fun transferToThisDeviceSucceededThenFarFromReceiver_viewStillDisplayedButDoesTimeOut() {
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
+ routeInfo,
+ null
+ )
+
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
+ routeInfo,
+ null
+ )
+ fakeExecutor.runAllReady()
+
+ verify(windowManager, never()).removeView(any())
+ verify(logger).logRemovalBypass(any(), any())
+
+ fakeClock.advanceTime(TIMEOUT + 1L)
+
+ verify(windowManager).removeView(any())
+ }
+
+ private fun getChipView(): ViewGroup {
+ val viewCaptor = ArgumentCaptor.forClass(View::class.java)
+ verify(windowManager).addView(viewCaptor.capture(), any())
+ return viewCaptor.value as ViewGroup
+ }
+
+ private fun ViewGroup.getChipText(): String =
+ (this.requireViewById<TextView>(R.id.text)).text as String
+
+ /** Helper method providing default parameters to not clutter up the tests. */
+ private fun almostCloseToStartCast() =
+ ChipSenderInfo(ChipStateSender.ALMOST_CLOSE_TO_START_CAST, routeInfo)
+
+ /** Helper method providing default parameters to not clutter up the tests. */
+ private fun almostCloseToEndCast() =
+ ChipSenderInfo(ChipStateSender.ALMOST_CLOSE_TO_END_CAST, routeInfo)
+
+ /** Helper method providing default parameters to not clutter up the tests. */
+ private fun transferToReceiverTriggered() =
+ ChipSenderInfo(ChipStateSender.TRANSFER_TO_RECEIVER_TRIGGERED, routeInfo)
+
+ /** Helper method providing default parameters to not clutter up the tests. */
+ private fun transferToThisDeviceTriggered() =
+ ChipSenderInfo(ChipStateSender.TRANSFER_TO_THIS_DEVICE_TRIGGERED, routeInfo)
+
+ /** Helper method providing default parameters to not clutter up the tests. */
+ private fun transferToReceiverSucceeded(undoCallback: IUndoMediaTransferCallback? = null) =
+ ChipSenderInfo(ChipStateSender.TRANSFER_TO_RECEIVER_SUCCEEDED, routeInfo, undoCallback)
+
+ /** Helper method providing default parameters to not clutter up the tests. */
+ private fun transferToThisDeviceSucceeded(undoCallback: IUndoMediaTransferCallback? = null) =
+ ChipSenderInfo(ChipStateSender.TRANSFER_TO_THIS_DEVICE_SUCCEEDED, routeInfo, undoCallback)
+
+ /** Helper method providing default parameters to not clutter up the tests. */
+ private fun transferToReceiverFailed() =
+ ChipSenderInfo(ChipStateSender.TRANSFER_TO_RECEIVER_FAILED, routeInfo)
+
+ /** Helper method providing default parameters to not clutter up the tests. */
+ private fun transferToThisDeviceFailed() =
+ ChipSenderInfo(ChipStateSender.TRANSFER_TO_RECEIVER_FAILED, routeInfo)
+}
+
+private const val OTHER_DEVICE_NAME = "My Tablet"
+private const val TIMEOUT = 10000
+
+private val routeInfo =
+ MediaRoute2Info.Builder("id", OTHER_DEVICE_NAME)
+ .addFeature("feature")
+ .setClientPackageName("com.android.systemui")
+ .build()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
index c76d9e7a2b20..0151822f871c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
@@ -645,6 +645,20 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
verify(animator).start()
}
+ @Test
+ fun privacyChipParentVisibleFromStart() {
+ verify(privacyIconsController).onParentVisible()
+ }
+
+ @Test
+ fun privacyChipParentVisibleAlways() {
+ controller.largeScreenActive = true
+ controller.largeScreenActive = false
+ controller.largeScreenActive = true
+
+ verify(privacyIconsController, never()).onParentInvisible()
+ }
+
private fun createWindowInsets(
topCutout: Rect? = Rect()
): WindowInsets {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt
index c4abedd0eed4..b68eb88d46db 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt
@@ -63,8 +63,6 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() {
@Mock
private lateinit var powerManager: PowerManager
- private var shouldIgnoreViewRemoval: Boolean = false
-
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
@@ -209,26 +207,6 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() {
verify(windowManager, never()).removeView(any())
}
- @Test
- fun removeView_shouldIgnoreRemovalFalse_viewRemoved() {
- shouldIgnoreViewRemoval = false
- underTest.displayView(getState())
-
- underTest.removeView("reason")
-
- verify(windowManager).removeView(any())
- }
-
- @Test
- fun removeView_shouldIgnoreRemovalTrue_viewNotRemoved() {
- shouldIgnoreViewRemoval = true
- underTest.displayView(getState())
-
- underTest.removeView("reason")
-
- verify(windowManager, never()).removeView(any())
- }
-
private fun getState(name: String = "name") = ViewInfo(name)
private fun getConfigurationListener(): ConfigurationListener {
@@ -253,7 +231,7 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() {
accessibilityManager,
configurationController,
powerManager,
- R.layout.media_ttt_chip,
+ R.layout.chipbar,
"Window Title",
"WAKE_REASON",
) {
@@ -267,10 +245,6 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() {
mostRecentViewInfo = newInfo
}
- override fun shouldIgnoreViewRemoval(info: ViewInfo, removalReason: String): Boolean {
- return shouldIgnoreViewRemoval
- }
-
override fun getTouchableRegion(view: View, outRect: Rect) {
outRect.setEmpty()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt
index 3a8a51d42f77..6225d0c722ae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt
@@ -14,10 +14,8 @@
* limitations under the License.
*/
-package com.android.systemui.media.taptotransfer.sender
+package com.android.systemui.temporarydisplay.chipbar
-import android.app.StatusBarManager
-import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
@@ -38,11 +36,11 @@ import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.media.taptotransfer.common.MediaTttLogger
-import com.android.systemui.media.taptotransfer.receiver.MediaTttReceiverLogger
+import com.android.systemui.media.taptotransfer.sender.ChipStateSender
+import com.android.systemui.media.taptotransfer.sender.MediaTttSenderUiEventLogger
+import com.android.systemui.media.taptotransfer.sender.MediaTttSenderUiEvents
import com.android.systemui.plugins.FalsingManager
-import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
@@ -63,8 +61,8 @@ import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper
-class MediaTttChipControllerSenderTest : SysuiTestCase() {
- private lateinit var controllerSender: TestMediaTttChipControllerSender
+class ChipbarCoordinatorTest : SysuiTestCase() {
+ private lateinit var underTest: FakeChipbarCoordinator
@Mock
private lateinit var packageManager: PackageManager
@@ -81,14 +79,11 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
@Mock
private lateinit var windowManager: WindowManager
@Mock
- private lateinit var commandQueue: CommandQueue
- @Mock
private lateinit var falsingManager: FalsingManager
@Mock
private lateinit var falsingCollector: FalsingCollector
@Mock
private lateinit var viewUtil: ViewUtil
- private lateinit var commandQueueCallback: CommandQueue.Callbacks
private lateinit var fakeAppIconDrawable: Drawable
private lateinit var fakeClock: FakeSystemClock
private lateinit var fakeExecutor: FakeExecutor
@@ -115,8 +110,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
whenever(accessibilityManager.getRecommendedTimeoutMillis(any(), any())).thenReturn(TIMEOUT)
- controllerSender = TestMediaTttChipControllerSender(
- commandQueue,
+ underTest = FakeChipbarCoordinator(
context,
logger,
windowManager,
@@ -129,200 +123,13 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
falsingCollector,
viewUtil,
)
- controllerSender.start()
-
- val callbackCaptor = ArgumentCaptor.forClass(CommandQueue.Callbacks::class.java)
- verify(commandQueue).addCallback(callbackCaptor.capture())
- commandQueueCallback = callbackCaptor.value!!
- }
-
- @Test
- fun commandQueueCallback_almostCloseToStartCast_triggersCorrectChip() {
- commandQueueCallback.updateMediaTapToTransferSenderDisplay(
- StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
- routeInfo,
- null
- )
-
- assertThat(getChipView().getChipText()).isEqualTo(
- almostCloseToStartCast().state.getChipTextString(context, OTHER_DEVICE_NAME)
- )
- assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
- MediaTttSenderUiEvents.MEDIA_TTT_SENDER_ALMOST_CLOSE_TO_START_CAST.id
- )
- }
-
- @Test
- fun commandQueueCallback_almostCloseToEndCast_triggersCorrectChip() {
- commandQueueCallback.updateMediaTapToTransferSenderDisplay(
- StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST,
- routeInfo,
- null
- )
-
- assertThat(getChipView().getChipText()).isEqualTo(
- almostCloseToEndCast().state.getChipTextString(context, OTHER_DEVICE_NAME)
- )
- assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
- MediaTttSenderUiEvents.MEDIA_TTT_SENDER_ALMOST_CLOSE_TO_END_CAST.id
- )
- }
-
- @Test
- fun commandQueueCallback_transferToReceiverTriggered_triggersCorrectChip() {
- commandQueueCallback.updateMediaTapToTransferSenderDisplay(
- StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED,
- routeInfo,
- null
- )
-
- assertThat(getChipView().getChipText()).isEqualTo(
- transferToReceiverTriggered().state.getChipTextString(context, OTHER_DEVICE_NAME)
- )
- assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
- MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_TRIGGERED.id
- )
- }
-
- @Test
- fun commandQueueCallback_transferToThisDeviceTriggered_triggersCorrectChip() {
- commandQueueCallback.updateMediaTapToTransferSenderDisplay(
- StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
- routeInfo,
- null
- )
-
- assertThat(getChipView().getChipText()).isEqualTo(
- transferToThisDeviceTriggered().state.getChipTextString(context, OTHER_DEVICE_NAME)
- )
- assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
- MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_TRIGGERED.id
- )
- }
-
- @Test
- fun commandQueueCallback_transferToReceiverSucceeded_triggersCorrectChip() {
- commandQueueCallback.updateMediaTapToTransferSenderDisplay(
- StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
- routeInfo,
- null
- )
-
- assertThat(getChipView().getChipText()).isEqualTo(
- transferToReceiverSucceeded().state.getChipTextString(context, OTHER_DEVICE_NAME)
- )
- assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
- MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_SUCCEEDED.id
- )
- }
-
- @Test
- fun commandQueueCallback_transferToThisDeviceSucceeded_triggersCorrectChip() {
- commandQueueCallback.updateMediaTapToTransferSenderDisplay(
- StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
- routeInfo,
- null
- )
-
- assertThat(getChipView().getChipText()).isEqualTo(
- transferToThisDeviceSucceeded().state.getChipTextString(context, OTHER_DEVICE_NAME)
- )
- assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
- MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_SUCCEEDED.id
- )
- }
-
- @Test
- fun commandQueueCallback_transferToReceiverFailed_triggersCorrectChip() {
- commandQueueCallback.updateMediaTapToTransferSenderDisplay(
- StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED,
- routeInfo,
- null
- )
-
- assertThat(getChipView().getChipText()).isEqualTo(
- transferToReceiverFailed().state.getChipTextString(context, OTHER_DEVICE_NAME)
- )
- assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
- MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_FAILED.id
- )
- }
-
- @Test
- fun commandQueueCallback_transferToThisDeviceFailed_triggersCorrectChip() {
- commandQueueCallback.updateMediaTapToTransferSenderDisplay(
- StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED,
- routeInfo,
- null
- )
-
- assertThat(getChipView().getChipText()).isEqualTo(
- transferToThisDeviceFailed().state.getChipTextString(context, OTHER_DEVICE_NAME)
- )
- assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
- MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_FAILED.id
- )
- }
-
- @Test
- fun commandQueueCallback_farFromReceiver_noChipShown() {
- commandQueueCallback.updateMediaTapToTransferSenderDisplay(
- StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
- routeInfo,
- null
- )
-
- verify(windowManager, never()).addView(any(), any())
- assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
- MediaTttSenderUiEvents.MEDIA_TTT_SENDER_FAR_FROM_RECEIVER.id
- )
- }
-
- @Test
- fun commandQueueCallback_almostCloseThenFarFromReceiver_chipShownThenHidden() {
- commandQueueCallback.updateMediaTapToTransferSenderDisplay(
- StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
- routeInfo,
- null
- )
-
- commandQueueCallback.updateMediaTapToTransferSenderDisplay(
- StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
- routeInfo,
- null
- )
-
- val viewCaptor = ArgumentCaptor.forClass(View::class.java)
- verify(windowManager).addView(viewCaptor.capture(), any())
- verify(windowManager).removeView(viewCaptor.value)
- }
-
- @Test
- fun commandQueueCallback_invalidStateParam_noChipShown() {
- commandQueueCallback.updateMediaTapToTransferSenderDisplay(
- 100,
- routeInfo,
- null
- )
-
- verify(windowManager, never()).addView(any(), any())
- }
-
- @Test
- fun receivesNewStateFromCommandQueue_isLogged() {
- commandQueueCallback.updateMediaTapToTransferSenderDisplay(
- StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
- routeInfo,
- null
- )
-
- verify(logger).logStateChange(any(), any(), any())
+ underTest.start()
}
@Test
fun almostCloseToStartCast_appIcon_deviceName_noLoadingIcon_noUndo_noFailureIcon() {
val state = almostCloseToStartCast()
- controllerSender.displayView(state)
+ underTest.displayView(state)
val chipView = getChipView()
assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable)
@@ -338,7 +145,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
@Test
fun almostCloseToEndCast_appIcon_deviceName_noLoadingIcon_noUndo_noFailureIcon() {
val state = almostCloseToEndCast()
- controllerSender.displayView(state)
+ underTest.displayView(state)
val chipView = getChipView()
assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable)
@@ -354,7 +161,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
@Test
fun transferToReceiverTriggered_appIcon_loadingIcon_noUndo_noFailureIcon() {
val state = transferToReceiverTriggered()
- controllerSender.displayView(state)
+ underTest.displayView(state)
val chipView = getChipView()
assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable)
@@ -370,7 +177,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
@Test
fun transferToThisDeviceTriggered_appIcon_loadingIcon_noUndo_noFailureIcon() {
val state = transferToThisDeviceTriggered()
- controllerSender.displayView(state)
+ underTest.displayView(state)
val chipView = getChipView()
assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable)
@@ -386,7 +193,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
@Test
fun transferToReceiverSucceeded_appIcon_deviceName_noLoadingIcon_noFailureIcon() {
val state = transferToReceiverSucceeded()
- controllerSender.displayView(state)
+ underTest.displayView(state)
val chipView = getChipView()
assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable)
@@ -400,7 +207,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
@Test
fun transferToReceiverSucceeded_nullUndoRunnable_noUndo() {
- controllerSender.displayView(transferToReceiverSucceeded(undoCallback = null))
+ underTest.displayView(transferToReceiverSucceeded(undoCallback = null))
val chipView = getChipView()
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE)
@@ -411,7 +218,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
val undoCallback = object : IUndoMediaTransferCallback.Stub() {
override fun onUndoTriggered() {}
}
- controllerSender.displayView(transferToReceiverSucceeded(undoCallback))
+ underTest.displayView(transferToReceiverSucceeded(undoCallback))
val chipView = getChipView()
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.VISIBLE)
@@ -427,7 +234,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
}
}
- controllerSender.displayView(transferToReceiverSucceeded(undoCallback))
+ underTest.displayView(transferToReceiverSucceeded(undoCallback))
getChipView().getUndoButton().performClick()
assertThat(undoCallbackCalled).isTrue()
@@ -443,7 +250,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
}
}
- controllerSender.displayView(transferToReceiverSucceeded(undoCallback))
+ underTest.displayView(transferToReceiverSucceeded(undoCallback))
getChipView().getUndoButton().performClick()
assertThat(undoCallbackCalled).isFalse()
@@ -459,7 +266,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
}
}
- controllerSender.displayView(transferToReceiverSucceeded(undoCallback))
+ underTest.displayView(transferToReceiverSucceeded(undoCallback))
getChipView().getUndoButton().performClick()
assertThat(undoCallbackCalled).isTrue()
@@ -470,7 +277,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
val undoCallback = object : IUndoMediaTransferCallback.Stub() {
override fun onUndoTriggered() {}
}
- controllerSender.displayView(transferToReceiverSucceeded(undoCallback))
+ underTest.displayView(transferToReceiverSucceeded(undoCallback))
getChipView().getUndoButton().performClick()
@@ -485,7 +292,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
@Test
fun transferToThisDeviceSucceeded_appIcon_deviceName_noLoadingIcon_noFailureIcon() {
val state = transferToThisDeviceSucceeded()
- controllerSender.displayView(state)
+ underTest.displayView(state)
val chipView = getChipView()
assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable)
@@ -499,7 +306,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
@Test
fun transferToThisDeviceSucceeded_nullUndoRunnable_noUndo() {
- controllerSender.displayView(transferToThisDeviceSucceeded(undoCallback = null))
+ underTest.displayView(transferToThisDeviceSucceeded(undoCallback = null))
val chipView = getChipView()
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE)
@@ -510,7 +317,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
val undoCallback = object : IUndoMediaTransferCallback.Stub() {
override fun onUndoTriggered() {}
}
- controllerSender.displayView(transferToThisDeviceSucceeded(undoCallback))
+ underTest.displayView(transferToThisDeviceSucceeded(undoCallback))
val chipView = getChipView()
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.VISIBLE)
@@ -526,7 +333,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
}
}
- controllerSender.displayView(transferToThisDeviceSucceeded(undoCallback))
+ underTest.displayView(transferToThisDeviceSucceeded(undoCallback))
getChipView().getUndoButton().performClick()
assertThat(undoCallbackCalled).isTrue()
@@ -537,7 +344,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
val undoCallback = object : IUndoMediaTransferCallback.Stub() {
override fun onUndoTriggered() {}
}
- controllerSender.displayView(transferToThisDeviceSucceeded(undoCallback))
+ underTest.displayView(transferToThisDeviceSucceeded(undoCallback))
getChipView().getUndoButton().performClick()
@@ -552,7 +359,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
@Test
fun transferToReceiverFailed_appIcon_noDeviceName_noLoadingIcon_noUndo_failureIcon() {
val state = transferToReceiverFailed()
- controllerSender.displayView(state)
+ underTest.displayView(state)
val chipView = getChipView()
assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable)
@@ -568,7 +375,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
@Test
fun transferToThisDeviceFailed_appIcon_noDeviceName_noLoadingIcon_noUndo_failureIcon() {
val state = transferToThisDeviceFailed()
- controllerSender.displayView(state)
+ underTest.displayView(state)
val chipView = getChipView()
assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable)
@@ -583,24 +390,24 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
@Test
fun changeFromAlmostCloseToStartToTransferTriggered_loadingIconAppears() {
- controllerSender.displayView(almostCloseToStartCast())
- controllerSender.displayView(transferToReceiverTriggered())
+ underTest.displayView(almostCloseToStartCast())
+ underTest.displayView(transferToReceiverTriggered())
assertThat(getChipView().getLoadingIconVisibility()).isEqualTo(View.VISIBLE)
}
@Test
fun changeFromTransferTriggeredToTransferSucceeded_loadingIconDisappears() {
- controllerSender.displayView(transferToReceiverTriggered())
- controllerSender.displayView(transferToReceiverSucceeded())
+ underTest.displayView(transferToReceiverTriggered())
+ underTest.displayView(transferToReceiverSucceeded())
assertThat(getChipView().getLoadingIconVisibility()).isEqualTo(View.GONE)
}
@Test
fun changeFromTransferTriggeredToTransferSucceeded_undoButtonAppears() {
- controllerSender.displayView(transferToReceiverTriggered())
- controllerSender.displayView(
+ underTest.displayView(transferToReceiverTriggered())
+ underTest.displayView(
transferToReceiverSucceeded(
object : IUndoMediaTransferCallback.Stub() {
override fun onUndoTriggered() {}
@@ -613,166 +420,20 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
@Test
fun changeFromTransferSucceededToAlmostCloseToStart_undoButtonDisappears() {
- controllerSender.displayView(transferToReceiverSucceeded())
- controllerSender.displayView(almostCloseToStartCast())
+ underTest.displayView(transferToReceiverSucceeded())
+ underTest.displayView(almostCloseToStartCast())
assertThat(getChipView().getUndoButton().visibility).isEqualTo(View.GONE)
}
@Test
fun changeFromTransferTriggeredToTransferFailed_failureIconAppears() {
- controllerSender.displayView(transferToReceiverTriggered())
- controllerSender.displayView(transferToReceiverFailed())
+ underTest.displayView(transferToReceiverTriggered())
+ underTest.displayView(transferToReceiverFailed())
assertThat(getChipView().getFailureIcon().visibility).isEqualTo(View.VISIBLE)
}
- @Test
- fun transferToReceiverTriggeredThenRemoveView_viewStillDisplayed() {
- controllerSender.displayView(transferToReceiverTriggered())
- fakeClock.advanceTime(1000L)
-
- controllerSender.removeView("fakeRemovalReason")
- fakeExecutor.runAllReady()
-
- verify(windowManager, never()).removeView(any())
- verify(logger).logRemovalBypass(any(), any())
- }
-
- @Test
- fun transferToReceiverTriggeredThenFarFromReceiver_viewStillDisplayed() {
- controllerSender.displayView(transferToReceiverTriggered())
-
- commandQueueCallback.updateMediaTapToTransferSenderDisplay(
- StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
- routeInfo,
- null
- )
- fakeExecutor.runAllReady()
-
- verify(windowManager, never()).removeView(any())
- verify(logger).logRemovalBypass(any(), any())
- }
-
- @Test
- fun transferToReceiverTriggeredThenRemoveView_eventuallyTimesOut() {
- controllerSender.displayView(transferToReceiverTriggered())
-
- controllerSender.removeView("fakeRemovalReason")
- fakeClock.advanceTime(TIMEOUT + 1L)
-
- verify(windowManager).removeView(any())
- }
-
- @Test
- fun transferToThisDeviceTriggeredThenRemoveView_viewStillDisplayed() {
- controllerSender.displayView(transferToThisDeviceTriggered())
- fakeClock.advanceTime(1000L)
-
- controllerSender.removeView("fakeRemovalReason")
- fakeExecutor.runAllReady()
-
- verify(windowManager, never()).removeView(any())
- verify(logger).logRemovalBypass(any(), any())
- }
-
- @Test
- fun transferToThisDeviceTriggeredThenRemoveView_eventuallyTimesOut() {
- controllerSender.displayView(transferToThisDeviceTriggered())
-
- controllerSender.removeView("fakeRemovalReason")
- fakeClock.advanceTime(TIMEOUT + 1L)
-
- verify(windowManager).removeView(any())
- }
-
- @Test
- fun transferToThisDeviceTriggeredThenFarFromReceiver_viewStillDisplayed() {
- controllerSender.displayView(transferToThisDeviceTriggered())
-
- commandQueueCallback.updateMediaTapToTransferSenderDisplay(
- StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
- routeInfo,
- null
- )
- fakeExecutor.runAllReady()
-
- verify(windowManager, never()).removeView(any())
- verify(logger).logRemovalBypass(any(), any())
- }
-
- @Test
- fun transferToReceiverSucceededThenRemoveView_viewStillDisplayed() {
- controllerSender.displayView(transferToReceiverSucceeded())
-
- controllerSender.removeView("fakeRemovalReason")
- fakeExecutor.runAllReady()
-
- verify(windowManager, never()).removeView(any())
- verify(logger).logRemovalBypass(any(), any())
- }
-
- @Test
- fun transferToReceiverSucceededThenRemoveView_eventuallyTimesOut() {
- controllerSender.displayView(transferToReceiverSucceeded())
-
- controllerSender.removeView("fakeRemovalReason")
- fakeClock.advanceTime(TIMEOUT + 1L)
-
- verify(windowManager).removeView(any())
- }
-
- @Test
- fun transferToReceiverSucceededThenFarFromReceiver_viewStillDisplayed() {
- controllerSender.displayView(transferToReceiverSucceeded())
-
- commandQueueCallback.updateMediaTapToTransferSenderDisplay(
- StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
- routeInfo,
- null
- )
- fakeExecutor.runAllReady()
-
- verify(windowManager, never()).removeView(any())
- verify(logger).logRemovalBypass(any(), any())
- }
-
- @Test
- fun transferToThisDeviceSucceededThenRemoveView_viewStillDisplayed() {
- controllerSender.displayView(transferToThisDeviceSucceeded())
-
- controllerSender.removeView("fakeRemovalReason")
- fakeExecutor.runAllReady()
-
- verify(windowManager, never()).removeView(any())
- verify(logger).logRemovalBypass(any(), any())
- }
-
- @Test
- fun transferToThisDeviceSucceededThenRemoveView_eventuallyTimesOut() {
- controllerSender.displayView(transferToThisDeviceSucceeded())
-
- controllerSender.removeView("fakeRemovalReason")
- fakeClock.advanceTime(TIMEOUT + 1L)
-
- verify(windowManager).removeView(any())
- }
-
- @Test
- fun transferToThisDeviceSucceededThenFarFromReceiver_viewStillDisplayed() {
- controllerSender.displayView(transferToThisDeviceSucceeded())
-
- commandQueueCallback.updateMediaTapToTransferSenderDisplay(
- StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
- routeInfo,
- null
- )
- fakeExecutor.runAllReady()
-
- verify(windowManager, never()).removeView(any())
- verify(logger).logRemovalBypass(any(), any())
- }
-
private fun ViewGroup.getAppIconView() = this.requireViewById<ImageView>(R.id.app_icon)
private fun ViewGroup.getChipText(): String =
@@ -791,6 +452,10 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
return viewCaptor.value as ViewGroup
}
+ // TODO(b/245610654): For now, the below methods are duplicated between this test and
+ // [MediaTttSenderCoordinatorTest]. Once we define a generic API for [ChipbarCoordinator],
+ // these will no longer be duplicated.
+
/** Helper method providing default parameters to not clutter up the tests. */
private fun almostCloseToStartCast() =
ChipSenderInfo(ChipStateSender.ALMOST_CLOSE_TO_START_CAST, routeInfo)
@@ -822,39 +487,6 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
/** Helper method providing default parameters to not clutter up the tests. */
private fun transferToThisDeviceFailed() =
ChipSenderInfo(ChipStateSender.TRANSFER_TO_RECEIVER_FAILED, routeInfo)
-
- private class TestMediaTttChipControllerSender(
- commandQueue: CommandQueue,
- context: Context,
- @MediaTttReceiverLogger logger: MediaTttLogger,
- windowManager: WindowManager,
- mainExecutor: DelayableExecutor,
- accessibilityManager: AccessibilityManager,
- configurationController: ConfigurationController,
- powerManager: PowerManager,
- uiEventLogger: MediaTttSenderUiEventLogger,
- falsingManager: FalsingManager,
- falsingCollector: FalsingCollector,
- viewUtil: ViewUtil,
- ) : MediaTttChipControllerSender(
- commandQueue,
- context,
- logger,
- windowManager,
- mainExecutor,
- accessibilityManager,
- configurationController,
- powerManager,
- uiEventLogger,
- falsingManager,
- falsingCollector,
- viewUtil,
- ) {
- override fun animateViewOut(view: ViewGroup, onAnimationEnd: Runnable) {
- // Just bypass the animation in tests
- onAnimationEnd.run()
- }
- }
}
private const val APP_NAME = "Fake app name"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/FakeChipbarCoordinator.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/FakeChipbarCoordinator.kt
new file mode 100644
index 000000000000..10704ac8fc67
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/FakeChipbarCoordinator.kt
@@ -0,0 +1,64 @@
+/*
+ * 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.temporarydisplay.chipbar
+
+import android.content.Context
+import android.os.PowerManager
+import android.view.ViewGroup
+import android.view.WindowManager
+import android.view.accessibility.AccessibilityManager
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.media.taptotransfer.common.MediaTttLogger
+import com.android.systemui.media.taptotransfer.receiver.MediaTttReceiverLogger
+import com.android.systemui.media.taptotransfer.sender.MediaTttSenderUiEventLogger
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.view.ViewUtil
+
+/** A fake implementation of [ChipbarCoordinator] for testing. */
+class FakeChipbarCoordinator(
+ context: Context,
+ @MediaTttReceiverLogger logger: MediaTttLogger,
+ windowManager: WindowManager,
+ mainExecutor: DelayableExecutor,
+ accessibilityManager: AccessibilityManager,
+ configurationController: ConfigurationController,
+ powerManager: PowerManager,
+ uiEventLogger: MediaTttSenderUiEventLogger,
+ falsingManager: FalsingManager,
+ falsingCollector: FalsingCollector,
+ viewUtil: ViewUtil,
+) :
+ ChipbarCoordinator(
+ context,
+ logger,
+ windowManager,
+ mainExecutor,
+ accessibilityManager,
+ configurationController,
+ powerManager,
+ uiEventLogger,
+ falsingManager,
+ falsingCollector,
+ viewUtil,
+ ) {
+ override fun animateViewOut(view: ViewGroup, onAnimationEnd: Runnable) {
+ // Just bypass the animation in tests
+ onAnimationEnd.run()
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 725b1f41372c..0c126805fb78 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -18,6 +18,7 @@
package com.android.systemui.keyguard.data.repository
import com.android.systemui.common.shared.model.Position
+import com.android.systemui.keyguard.shared.model.StatusBarState
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -44,6 +45,9 @@ class FakeKeyguardRepository : KeyguardRepository {
private val _dozeAmount = MutableStateFlow(0f)
override val dozeAmount: Flow<Float> = _dozeAmount
+ private val _statusBarState = MutableStateFlow(StatusBarState.SHADE)
+ override val statusBarState: Flow<StatusBarState> = _statusBarState
+
override fun isKeyguardShowing(): Boolean {
return _isKeyguardShowing.value
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 6417db0eb050..29194c58bd0c 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -657,25 +657,27 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
userState.mBindingServices.removeIf(filter);
userState.mCrashedServices.removeIf(filter);
final Iterator<ComponentName> it = userState.mEnabledServices.iterator();
+ boolean anyServiceRemoved = false;
while (it.hasNext()) {
final ComponentName comp = it.next();
final String compPkg = comp.getPackageName();
if (compPkg.equals(packageName)) {
it.remove();
- // Update the enabled services setting.
- persistComponentNamesToSettingLocked(
- Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
- userState.mEnabledServices, userId);
- // Update the touch exploration granted services setting.
userState.mTouchExplorationGrantedServices.remove(comp);
- persistComponentNamesToSettingLocked(
- Settings.Secure.
- TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
- userState.mTouchExplorationGrantedServices, userId);
- onUserStateChangedLocked(userState);
- return;
+ anyServiceRemoved = true;
}
}
+ if (anyServiceRemoved) {
+ // Update the enabled services setting.
+ persistComponentNamesToSettingLocked(
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+ userState.mEnabledServices, userId);
+ // Update the touch exploration granted services setting.
+ persistComponentNamesToSettingLocked(
+ Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+ userState.mTouchExplorationGrantedServices, userId);
+ onUserStateChangedLocked(userState);
+ }
}
}
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 17215e5ae4ad..8f59ffd30bba 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -220,6 +220,11 @@ public class BrightnessTracker {
}
private void backgroundStart(float initialBrightness) {
+ synchronized (mDataCollectionLock) {
+ if (mStarted) {
+ return;
+ }
+ }
if (DEBUG) {
Slog.d(TAG, "Background start");
}
@@ -250,6 +255,11 @@ public class BrightnessTracker {
/** Stop listening for events */
void stop() {
+ synchronized (mDataCollectionLock) {
+ if (!mStarted) {
+ return;
+ }
+ }
if (DEBUG) {
Slog.d(TAG, "Stop");
}
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 1ae37bb5d66b..7858516bab67 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -150,7 +150,7 @@ import javax.xml.datatype.DatatypeConfigurationException;
* <quirk>canSetBrightnessViaHwc</quirk>
* </quirks>
*
- * <autoBrightness>
+ * <autoBrightness enable="true">
* <brighteningLightDebounceMillis>
* 2000
* </brighteningLightDebounceMillis>
@@ -507,6 +507,11 @@ public class DisplayDeviceConfig {
private long mAutoBrightnessDarkeningLightDebounce =
INVALID_AUTO_BRIGHTNESS_LIGHT_DEBOUNCE;
+ // This setting allows non-default displays to have autobrightness enabled.
+ private boolean mAutoBrightnessAvailable = false;
+ // This stores the raw value loaded from the config file - true if not written.
+ private boolean mDdcAutoBrightnessAvailable = true;
+
// Brightness Throttling data may be updated via the DeviceConfig. Here we store the original
// data, which comes from the ddc, and the current one, which may be the DeviceConfig
// overwritten value.
@@ -1119,6 +1124,10 @@ public class DisplayDeviceConfig {
return mProximitySensor;
}
+ boolean isAutoBrightnessAvailable() {
+ return mAutoBrightnessAvailable;
+ }
+
/**
* @param quirkValue The quirk to test.
* @return {@code true} if the specified quirk is present in this configuration, {@code false}
@@ -1271,6 +1280,8 @@ public class DisplayDeviceConfig {
+ mAutoBrightnessDarkeningLightDebounce
+ ", mBrightnessLevelsLux= " + Arrays.toString(mBrightnessLevelsLux)
+ ", mBrightnessLevelsNits= " + Arrays.toString(mBrightnessLevelsNits)
+ + ", mDdcAutoBrightnessAvailable= " + mDdcAutoBrightnessAvailable
+ + ", mAutoBrightnessAvailable= " + mAutoBrightnessAvailable
+ "}";
}
@@ -1349,6 +1360,7 @@ public class DisplayDeviceConfig {
loadBrightnessChangeThresholdsFromXml();
setProxSensorUnspecified();
loadAutoBrightnessConfigsFromConfigXml();
+ loadAutoBrightnessAvailableFromConfigXml();
mLoadedFrom = "<config.xml>";
}
@@ -1367,6 +1379,7 @@ public class DisplayDeviceConfig {
setSimpleMappingStrategyValues();
loadAmbientLightSensorFromConfigXml();
setProxSensorUnspecified();
+ loadAutoBrightnessAvailableFromConfigXml();
}
private void copyUninitializedValuesFromSecondaryConfig(DisplayConfiguration defaultConfig) {
@@ -1559,9 +1572,11 @@ public class DisplayDeviceConfig {
}
private void loadAutoBrightnessConfigValues(DisplayConfiguration config) {
- loadAutoBrightnessBrighteningLightDebounce(config.getAutoBrightness());
- loadAutoBrightnessDarkeningLightDebounce(config.getAutoBrightness());
- loadAutoBrightnessDisplayBrightnessMapping(config.getAutoBrightness());
+ final AutoBrightness autoBrightness = config.getAutoBrightness();
+ loadAutoBrightnessBrighteningLightDebounce(autoBrightness);
+ loadAutoBrightnessDarkeningLightDebounce(autoBrightness);
+ loadAutoBrightnessDisplayBrightnessMapping(autoBrightness);
+ loadEnableAutoBrightness(autoBrightness);
}
/**
@@ -1623,6 +1638,11 @@ public class DisplayDeviceConfig {
}
}
+ private void loadAutoBrightnessAvailableFromConfigXml() {
+ mAutoBrightnessAvailable = mContext.getResources().getBoolean(
+ R.bool.config_automatic_brightness_available);
+ }
+
private void loadBrightnessMapFromConfigXml() {
// Use the config.xml mapping
final Resources res = mContext.getResources();
@@ -2263,6 +2283,20 @@ public class DisplayDeviceConfig {
return levels;
}
+ private void loadEnableAutoBrightness(AutoBrightness autobrightness) {
+ // mDdcAutoBrightnessAvailable is initialised to true, so that we fallback to using the
+ // config.xml values if the autobrightness tag is not defined in the ddc file.
+ // Autobrightness can still be turned off globally via config_automatic_brightness_available
+ mDdcAutoBrightnessAvailable = true;
+ if (autobrightness != null) {
+ mDdcAutoBrightnessAvailable = autobrightness.getEnabled();
+ }
+
+ mAutoBrightnessAvailable = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_automatic_brightness_available)
+ && mDdcAutoBrightnessAvailable;
+ }
+
static class SensorData {
public String type;
public String name;
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index b153c1ba98e0..a1490e564787 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1759,9 +1759,13 @@ public final class DisplayManagerService extends SystemService {
if (displayDevice == null) {
return;
}
- mPersistentDataStore.setUserPreferredResolution(
- displayDevice, resolutionWidth, resolutionHeight);
- mPersistentDataStore.setUserPreferredRefreshRate(displayDevice, refreshRate);
+ try {
+ mPersistentDataStore.setUserPreferredResolution(
+ displayDevice, resolutionWidth, resolutionHeight);
+ mPersistentDataStore.setUserPreferredRefreshRate(displayDevice, refreshRate);
+ } finally {
+ mPersistentDataStore.saveIfNeeded();
+ }
}
private void setUserPreferredModeForDisplayLocked(int displayId, Display.Mode mode) {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 458cf1a31b97..95dc23fc3120 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -558,13 +558,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mScreenBrightnessForVrRangeMinimum = clampAbsoluteBrightness(
pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR));
- // Check the setting, but also verify that it is the default display. Only the default
- // display has an automatic brightness controller running.
- // TODO: b/179021925 - Fix to work with multiple displays
- mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
- com.android.internal.R.bool.config_automatic_brightness_available)
- && mDisplayId == Display.DEFAULT_DISPLAY;
-
mAllowAutoBrightnessWhileDozingConfig = resources.getBoolean(
com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing);
@@ -938,6 +931,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
private void setUpAutoBrightness(Resources resources, Handler handler) {
+ mUseSoftwareAutoBrightnessConfig = mDisplayDeviceConfig.isAutoBrightnessAvailable();
+
if (!mUseSoftwareAutoBrightnessConfig) {
return;
}
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
index b9a0738d15c4..a11f1721a4b9 100644
--- a/services/core/java/com/android/server/display/PersistentDataStore.java
+++ b/services/core/java/com/android/server/display/PersistentDataStore.java
@@ -75,6 +75,11 @@ import java.util.Objects;
* &lt;/brightness-curve>
* &lt;/brightness-configuration>
* &lt;/brightness-configurations>
+ * &lt;display-mode>0&lt;
+ * &lt;resolution-width>1080&lt;/resolution-width>
+ * &lt;resolution-height>1920&lt;/resolution-height>
+ * &lt;refresh-rate>60&lt;/refresh-rate>
+ * &lt;/display-mode>
* &lt;/display>
* &lt;/display-states>
* &lt;stable-device-values>
@@ -121,6 +126,10 @@ final class PersistentDataStore {
private static final String ATTR_PACKAGE_NAME = "package-name";
private static final String ATTR_TIME_STAMP = "timestamp";
+ private static final String TAG_RESOLUTION_WIDTH = "resolution-width";
+ private static final String TAG_RESOLUTION_HEIGHT = "resolution-height";
+ private static final String TAG_REFRESH_RATE = "refresh-rate";
+
// Remembered Wifi display devices.
private ArrayList<WifiDisplay> mRememberedWifiDisplays = new ArrayList<WifiDisplay>();
@@ -696,6 +705,18 @@ final class PersistentDataStore {
case TAG_BRIGHTNESS_CONFIGURATIONS:
mDisplayBrightnessConfigurations.loadFromXml(parser);
break;
+ case TAG_RESOLUTION_WIDTH:
+ String width = parser.nextText();
+ mWidth = Integer.parseInt(width);
+ break;
+ case TAG_RESOLUTION_HEIGHT:
+ String height = parser.nextText();
+ mHeight = Integer.parseInt(height);
+ break;
+ case TAG_REFRESH_RATE:
+ String refreshRate = parser.nextText();
+ mRefreshRate = Float.parseFloat(refreshRate);
+ break;
}
}
}
@@ -712,6 +733,18 @@ final class PersistentDataStore {
serializer.startTag(null, TAG_BRIGHTNESS_CONFIGURATIONS);
mDisplayBrightnessConfigurations.saveToXml(serializer);
serializer.endTag(null, TAG_BRIGHTNESS_CONFIGURATIONS);
+
+ serializer.startTag(null, TAG_RESOLUTION_WIDTH);
+ serializer.text(Integer.toString(mWidth));
+ serializer.endTag(null, TAG_RESOLUTION_WIDTH);
+
+ serializer.startTag(null, TAG_RESOLUTION_HEIGHT);
+ serializer.text(Integer.toString(mHeight));
+ serializer.endTag(null, TAG_RESOLUTION_HEIGHT);
+
+ serializer.startTag(null, TAG_REFRESH_RATE);
+ serializer.text(Float.toString(mRefreshRate));
+ serializer.endTag(null, TAG_REFRESH_RATE);
}
public void dump(final PrintWriter pw, final String prefix) {
@@ -719,6 +752,8 @@ final class PersistentDataStore {
pw.println(prefix + "BrightnessValue=" + mBrightness);
pw.println(prefix + "DisplayBrightnessConfigurations: ");
mDisplayBrightnessConfigurations.dump(pw, prefix);
+ pw.println(prefix + "Resolution=" + mWidth + " " + mHeight);
+ pw.println(prefix + "RefreshRate=" + mRefreshRate);
}
}
diff --git a/services/core/java/com/android/server/power/AmbientDisplaySuppressionController.java b/services/core/java/com/android/server/power/AmbientDisplaySuppressionController.java
index aad7b1457b3c..7440fc75bf51 100644
--- a/services/core/java/com/android/server/power/AmbientDisplaySuppressionController.java
+++ b/services/core/java/com/android/server/power/AmbientDisplaySuppressionController.java
@@ -40,13 +40,24 @@ import java.util.Set;
public class AmbientDisplaySuppressionController {
private static final String TAG = "AmbientDisplaySuppressionController";
- private final Context mContext;
private final Set<Pair<String, Integer>> mSuppressionTokens;
+ private final AmbientDisplaySuppressionChangedCallback mCallback;
private IStatusBarService mStatusBarService;
- AmbientDisplaySuppressionController(Context context) {
- mContext = requireNonNull(context);
+ /** Interface to get a list of available logical devices. */
+ interface AmbientDisplaySuppressionChangedCallback {
+ /**
+ * Called when the suppression state changes.
+ *
+ * @param isSuppressed Whether ambient is suppressed.
+ */
+ void onSuppressionChanged(boolean isSuppressed);
+ }
+
+ AmbientDisplaySuppressionController(
+ @NonNull AmbientDisplaySuppressionChangedCallback callback) {
mSuppressionTokens = Collections.synchronizedSet(new ArraySet<>());
+ mCallback = requireNonNull(callback);
}
/**
@@ -58,6 +69,7 @@ public class AmbientDisplaySuppressionController {
*/
public void suppress(@NonNull String token, int callingUid, boolean suppress) {
Pair<String, Integer> suppressionToken = Pair.create(requireNonNull(token), callingUid);
+ final boolean wasSuppressed = isSuppressed();
if (suppress) {
mSuppressionTokens.add(suppressionToken);
@@ -65,9 +77,14 @@ public class AmbientDisplaySuppressionController {
mSuppressionTokens.remove(suppressionToken);
}
+ final boolean isSuppressed = isSuppressed();
+ if (isSuppressed != wasSuppressed) {
+ mCallback.onSuppressionChanged(isSuppressed);
+ }
+
try {
synchronized (mSuppressionTokens) {
- getStatusBar().suppressAmbientDisplay(isSuppressed());
+ getStatusBar().suppressAmbientDisplay(isSuppressed);
}
} catch (RemoteException e) {
Slog.e(TAG, "Failed to suppress ambient display", e);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index a63647cc1549..4ec92ec9190b 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -127,6 +127,7 @@ import com.android.server.am.BatteryStatsService;
import com.android.server.lights.LightsManager;
import com.android.server.lights.LogicalLight;
import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.power.AmbientDisplaySuppressionController.AmbientDisplaySuppressionChangedCallback;
import com.android.server.power.batterysaver.BatterySaverController;
import com.android.server.power.batterysaver.BatterySaverPolicy;
import com.android.server.power.batterysaver.BatterySaverStateMachine;
@@ -507,6 +508,9 @@ public final class PowerManagerService extends SystemService
// effectively and terminate the dream. Use -1 to disable this safety feature.
private int mDreamsBatteryLevelDrainCutoffConfig;
+ // Whether dreams should be disabled when ambient mode is suppressed.
+ private boolean mDreamsDisabledByAmbientModeSuppressionConfig;
+
// True if dreams are enabled by the user.
private boolean mDreamsEnabledSetting;
@@ -964,8 +968,8 @@ public final class PowerManagerService extends SystemService
}
AmbientDisplaySuppressionController createAmbientDisplaySuppressionController(
- Context context) {
- return new AmbientDisplaySuppressionController(context);
+ @NonNull AmbientDisplaySuppressionChangedCallback callback) {
+ return new AmbientDisplaySuppressionController(callback);
}
InattentiveSleepWarningController createInattentiveSleepWarningController() {
@@ -1044,7 +1048,8 @@ public final class PowerManagerService extends SystemService
mConstants = new Constants(mHandler);
mAmbientDisplayConfiguration = mInjector.createAmbientDisplayConfiguration(context);
mAmbientDisplaySuppressionController =
- mInjector.createAmbientDisplaySuppressionController(context);
+ mInjector.createAmbientDisplaySuppressionController(
+ mAmbientSuppressionChangedCallback);
mAttentionDetector = new AttentionDetector(this::onUserAttention, mLock);
mFaceDownDetector = new FaceDownDetector(this::onFlip);
mScreenUndimDetector = new ScreenUndimDetector();
@@ -1403,6 +1408,8 @@ public final class PowerManagerService extends SystemService
com.android.internal.R.integer.config_dreamsBatteryLevelMinimumWhenNotPowered);
mDreamsBatteryLevelDrainCutoffConfig = resources.getInteger(
com.android.internal.R.integer.config_dreamsBatteryLevelDrainCutoff);
+ mDreamsDisabledByAmbientModeSuppressionConfig = resources.getBoolean(
+ com.android.internal.R.bool.config_dreamsDisabledByAmbientModeSuppressionConfig);
mDozeAfterScreenOff = resources.getBoolean(
com.android.internal.R.bool.config_dozeAfterScreenOffByDefault);
mMinimumScreenOffTimeoutConfig = resources.getInteger(
@@ -3329,7 +3336,7 @@ public final class PowerManagerService extends SystemService
}
// Doze has ended or will be stopped. Update the power state.
- sleepPowerGroupLocked(powerGroup, now, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
+ sleepPowerGroupLocked(powerGroup, now, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
Process.SYSTEM_UID);
}
}
@@ -3340,12 +3347,32 @@ public final class PowerManagerService extends SystemService
}
}
+ @GuardedBy("mLock")
+ private void onDreamSuppressionChangedLocked(final boolean isSuppressed) {
+ if (!mDreamsDisabledByAmbientModeSuppressionConfig) {
+ return;
+ }
+ if (!isSuppressed && mIsPowered && mDreamsSupportedConfig && mDreamsEnabledSetting
+ && shouldNapAtBedTimeLocked() && isItBedTimeYetLocked(
+ mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP))) {
+ napInternal(SystemClock.uptimeMillis(), Process.SYSTEM_UID, /* allowWake= */ true);
+ } else if (isSuppressed) {
+ mDirty |= DIRTY_SETTINGS;
+ updatePowerStateLocked();
+ }
+ }
+
+
/**
* Returns true if the {@code groupId} is allowed to dream in its current state.
*/
@GuardedBy("mLock")
private boolean canDreamLocked(final PowerGroup powerGroup) {
+ final boolean dreamsSuppressed = mDreamsDisabledByAmbientModeSuppressionConfig
+ && mAmbientDisplaySuppressionController.isSuppressed();
+
if (!mBootCompleted
+ || dreamsSuppressed
|| getGlobalWakefulnessLocked() != WAKEFULNESS_DREAMING
|| !mDreamsSupportedConfig
|| !mDreamsEnabledSetting
@@ -5037,6 +5064,16 @@ public final class PowerManagerService extends SystemService
}
};
+ private final AmbientDisplaySuppressionChangedCallback mAmbientSuppressionChangedCallback =
+ new AmbientDisplaySuppressionChangedCallback() {
+ @Override
+ public void onSuppressionChanged(boolean isSuppressed) {
+ synchronized (mLock) {
+ onDreamSuppressionChangedLocked(isSuppressed);
+ }
+ }
+ };
+
/**
* Callback for asynchronous operations performed by the power manager.
*/
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index f25929c36060..189b86fd0ff1 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1166,7 +1166,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
try {
connection.mService.attach(connection, mToken, TYPE_WALLPAPER, false,
wpdData.mWidth, wpdData.mHeight,
- wpdData.mPadding, mDisplayId);
+ wpdData.mPadding, mDisplayId, FLAG_SYSTEM | FLAG_LOCK);
} catch (RemoteException e) {
Slog.w(TAG, "Failed attaching wallpaper on display", e);
if (wallpaper != null && !wallpaper.wallpaperUpdating
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index 30454d45574e..9f502ab6ca10 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -389,9 +389,9 @@ public class ActivityStartController {
SafeActivityOptions bottomOptions = null;
if (options != null) {
// To ensure the first N-1 activities (N == total # of activities) are also launched
- // into the correct display, use a copy of the passed-in options (keeping only
- // display-related info) for these activities.
- bottomOptions = options.selectiveCloneDisplayOptions();
+ // into the correct display and root task, use a copy of the passed-in options (keeping
+ // only display-related and launch-root-task information) for these activities.
+ bottomOptions = options.selectiveCloneLaunchOptions();
}
try {
intents = ArrayUtils.filterNotNull(intents, Intent[]::new);
diff --git a/services/core/java/com/android/server/wm/SafeActivityOptions.java b/services/core/java/com/android/server/wm/SafeActivityOptions.java
index e69a732b3fde..6d1b5fa6034d 100644
--- a/services/core/java/com/android/server/wm/SafeActivityOptions.java
+++ b/services/core/java/com/android/server/wm/SafeActivityOptions.java
@@ -117,13 +117,13 @@ public class SafeActivityOptions {
/**
* To ensure that two activities, one using this object, and the other using the
- * SafeActivityOptions returned from this function, are launched into the same display through
- * ActivityStartController#startActivities, all display-related information, i.e.
- * displayAreaToken, launchDisplayId and callerDisplayId, are cloned.
+ * SafeActivityOptions returned from this function, are launched into the same display/root task
+ * through ActivityStartController#startActivities, all display-related information, i.e.
+ * displayAreaToken, launchDisplayId, callerDisplayId and the launch root task are cloned.
*/
- @Nullable SafeActivityOptions selectiveCloneDisplayOptions() {
- final ActivityOptions options = cloneLaunchingDisplayOptions(mOriginalOptions);
- final ActivityOptions callerOptions = cloneLaunchingDisplayOptions(mCallerOptions);
+ @Nullable SafeActivityOptions selectiveCloneLaunchOptions() {
+ final ActivityOptions options = cloneLaunchingOptions(mOriginalOptions);
+ final ActivityOptions callerOptions = cloneLaunchingOptions(mCallerOptions);
if (options == null && callerOptions == null) {
return null;
}
@@ -136,11 +136,12 @@ public class SafeActivityOptions {
return safeOptions;
}
- private ActivityOptions cloneLaunchingDisplayOptions(ActivityOptions options) {
+ private ActivityOptions cloneLaunchingOptions(ActivityOptions options) {
return options == null ? null : ActivityOptions.makeBasic()
.setLaunchTaskDisplayArea(options.getLaunchTaskDisplayArea())
.setLaunchDisplayId(options.getLaunchDisplayId())
- .setCallerDisplayId((options.getCallerDisplayId()));
+ .setCallerDisplayId(options.getCallerDisplayId())
+ .setLaunchRootTask(options.getLaunchRootTask());
}
/**
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index 4a51b831da57..f53a1cfcfb3c 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -383,6 +383,7 @@
</xs:complexType>
<xs:complexType name="autoBrightness">
+ <xs:attribute name="enabled" type="xs:boolean" use="optional" default="true"/>
<xs:sequence>
<!-- Sets the debounce for autoBrightness brightening in millis-->
<xs:element name="brighteningLightDebounceMillis" type="xs:nonNegativeInteger"
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index 748ef4be9cc7..d89bd7cc9aa2 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -6,9 +6,11 @@ package com.android.server.display.config {
method public final java.math.BigInteger getBrighteningLightDebounceMillis();
method public final java.math.BigInteger getDarkeningLightDebounceMillis();
method public final com.android.server.display.config.DisplayBrightnessMapping getDisplayBrightnessMapping();
+ method public boolean getEnabled();
method public final void setBrighteningLightDebounceMillis(java.math.BigInteger);
method public final void setDarkeningLightDebounceMillis(java.math.BigInteger);
method public final void setDisplayBrightnessMapping(com.android.server.display.config.DisplayBrightnessMapping);
+ method public void setEnabled(boolean);
}
public class BrightnessThresholds {
diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SystemStubMultiUserDisableUninstallTest.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SystemStubMultiUserDisableUninstallTest.kt
index 45e0d09a1753..4ef6875dd310 100644
--- a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SystemStubMultiUserDisableUninstallTest.kt
+++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SystemStubMultiUserDisableUninstallTest.kt
@@ -628,6 +628,7 @@ class SystemStubMultiUserDisableUninstallTest : BaseHostJUnit4Test() {
CodePath.SAME, CodePath.DIFFERENT ->
throw AssertionError("secondDataPath cannot be a data path")
CodePath.SYSTEM -> assertThat(codePaths[1]).isEqualTo(stubFile.parent.toString())
+ else -> {}
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
index b9d6b2ccd306..994df2288a5c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
@@ -392,7 +392,7 @@ class SuspendPackageHelperTest : PackageHelperTestBase() {
whenever(rule.mocks().appsFilter.getVisibilityAllowList(
any(PackageDataSnapshot::class.java),
argThat { it?.packageName == pkgSetting.packageName }, any(IntArray::class.java),
- any() as ArrayMap<String, out PackageStateInternal>
+ any<ArrayMap<String, out PackageStateInternal>>()
))
.thenReturn(list)
}
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index 356600d84099..06422281ab25 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -885,6 +886,29 @@ public class BrightnessTrackerTest {
assertNull(mInjector.mLightSensor);
}
+ @Test
+ public void testOnlyOneReceiverRegistered() {
+ assertNull(mInjector.mLightSensor);
+ assertNull(mInjector.mSensorListener);
+ startTracker(mTracker, 0.3f, false);
+
+ assertNotNull(mInjector.mLightSensor);
+ assertNotNull(mInjector.mSensorListener);
+ Sensor registeredLightSensor = mInjector.mLightSensor;
+ SensorEventListener registeredSensorListener = mInjector.mSensorListener;
+
+ mTracker.start(0.3f);
+ assertSame(registeredLightSensor, mInjector.mLightSensor);
+ assertSame(registeredSensorListener, mInjector.mSensorListener);
+
+ mTracker.stop();
+ assertNull(mInjector.mLightSensor);
+ assertNull(mInjector.mSensorListener);
+
+ // mInjector asserts that we aren't removing a null receiver
+ mTracker.stop();
+ }
+
private InputStream getInputStream(String data) {
return new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
}
diff --git a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
index 9fe8609c85a1..3b0a22f80c30 100644
--- a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
@@ -275,6 +275,75 @@ public class PersistentDataStoreTest {
assertNull(mDataStore.getBrightnessConfiguration(userSerial));
}
+ @Test
+ public void testStoreAndRestoreResolution() {
+ final String uniqueDisplayId = "test:123";
+ DisplayDevice testDisplayDevice = new DisplayDevice(null, null, uniqueDisplayId, null) {
+ @Override
+ public boolean hasStableUniqueId() {
+ return true;
+ }
+
+ @Override
+ public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
+ return null;
+ }
+ };
+ int width = 35;
+ int height = 45;
+ mDataStore.loadIfNeeded();
+ mDataStore.setUserPreferredResolution(testDisplayDevice, width, height);
+
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ mInjector.setWriteStream(baos);
+ mDataStore.saveIfNeeded();
+ mTestLooper.dispatchAll();
+ assertTrue(mInjector.wasWriteSuccessful());
+ TestInjector newInjector = new TestInjector();
+ PersistentDataStore newDataStore = new PersistentDataStore(newInjector);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ newInjector.setReadStream(bais);
+ newDataStore.loadIfNeeded();
+ assertNotNull(newDataStore.getUserPreferredResolution(testDisplayDevice));
+ assertEquals(35, newDataStore.getUserPreferredResolution(testDisplayDevice).x);
+ assertEquals(35, mDataStore.getUserPreferredResolution(testDisplayDevice).x);
+ assertEquals(45, newDataStore.getUserPreferredResolution(testDisplayDevice).y);
+ assertEquals(45, mDataStore.getUserPreferredResolution(testDisplayDevice).y);
+ }
+
+ @Test
+ public void testStoreAndRestoreRefreshRate() {
+ final String uniqueDisplayId = "test:123";
+ DisplayDevice testDisplayDevice = new DisplayDevice(null, null, uniqueDisplayId, null) {
+ @Override
+ public boolean hasStableUniqueId() {
+ return true;
+ }
+
+ @Override
+ public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
+ return null;
+ }
+ };
+ float refreshRate = 85.3f;
+ mDataStore.loadIfNeeded();
+ mDataStore.setUserPreferredRefreshRate(testDisplayDevice, refreshRate);
+
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ mInjector.setWriteStream(baos);
+ mDataStore.saveIfNeeded();
+ mTestLooper.dispatchAll();
+ assertTrue(mInjector.wasWriteSuccessful());
+ TestInjector newInjector = new TestInjector();
+ PersistentDataStore newDataStore = new PersistentDataStore(newInjector);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ newInjector.setReadStream(bais);
+ newDataStore.loadIfNeeded();
+ assertNotNull(newDataStore.getUserPreferredRefreshRate(testDisplayDevice));
+ assertEquals(85.3f, mDataStore.getUserPreferredRefreshRate(testDisplayDevice), 01.f);
+ assertEquals(85.3f, newDataStore.getUserPreferredRefreshRate(testDisplayDevice), 0.1f);
+ }
+
public class TestInjector extends PersistentDataStore.Injector {
private InputStream mReadStream;
private OutputStream mWriteStream;
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 2d0cbfd27289..f5ed41a7fa8b 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -393,6 +393,12 @@ public class PowerManagerServiceTest {
.thenReturn(minimumScreenOffTimeoutConfigMillis);
}
+ private void setDreamsDisabledByAmbientModeSuppressionConfig(boolean disable) {
+ when(mResourcesSpy.getBoolean(
+ com.android.internal.R.bool.config_dreamsDisabledByAmbientModeSuppressionConfig))
+ .thenReturn(disable);
+ }
+
private void advanceTime(long timeMs) {
mClock.fastForward(timeMs);
mTestLooper.dispatchAll();
@@ -790,6 +796,91 @@ public class PowerManagerServiceTest {
assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
}
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testAmbientSuppression_disablesDreamingAndWakesDevice() {
+ Settings.Secure.putInt(mContextSpy.getContentResolver(),
+ Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1);
+ Settings.Secure.putInt(mContextSpy.getContentResolver(),
+ Settings.Secure.SCREENSAVER_ENABLED, 1);
+
+ setDreamsDisabledByAmbientModeSuppressionConfig(true);
+ setMinimumScreenOffTimeoutConfig(10000);
+ createService();
+ startSystem();
+
+ doAnswer(inv -> {
+ when(mDreamManagerInternalMock.isDreaming()).thenReturn(true);
+ return null;
+ }).when(mDreamManagerInternalMock).startDream(anyBoolean(), anyString());
+
+ setPluggedIn(true);
+ // Allow asynchronous sandman calls to execute.
+ advanceTime(10000);
+
+ forceDream();
+ assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
+ mService.getBinderServiceInstance().suppressAmbientDisplay("test", true);
+ advanceTime(50);
+ assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testAmbientSuppressionDisabled_shouldNotWakeDevice() {
+ Settings.Secure.putInt(mContextSpy.getContentResolver(),
+ Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1);
+ Settings.Secure.putInt(mContextSpy.getContentResolver(),
+ Settings.Secure.SCREENSAVER_ENABLED, 1);
+
+ setDreamsDisabledByAmbientModeSuppressionConfig(false);
+ setMinimumScreenOffTimeoutConfig(10000);
+ createService();
+ startSystem();
+
+ doAnswer(inv -> {
+ when(mDreamManagerInternalMock.isDreaming()).thenReturn(true);
+ return null;
+ }).when(mDreamManagerInternalMock).startDream(anyBoolean(), anyString());
+
+ setPluggedIn(true);
+ // Allow asynchronous sandman calls to execute.
+ advanceTime(10000);
+
+ forceDream();
+ assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
+ mService.getBinderServiceInstance().suppressAmbientDisplay("test", true);
+ advanceTime(50);
+ assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
+ }
+
+ @Test
+ public void testAmbientSuppression_doesNotAffectDreamForcing() {
+ Settings.Secure.putInt(mContextSpy.getContentResolver(),
+ Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1);
+ Settings.Secure.putInt(mContextSpy.getContentResolver(),
+ Settings.Secure.SCREENSAVER_ENABLED, 1);
+
+ setDreamsDisabledByAmbientModeSuppressionConfig(true);
+ setMinimumScreenOffTimeoutConfig(10000);
+ createService();
+ startSystem();
+
+ doAnswer(inv -> {
+ when(mDreamManagerInternalMock.isDreaming()).thenReturn(true);
+ return null;
+ }).when(mDreamManagerInternalMock).startDream(anyBoolean(), anyString());
+
+ mService.getBinderServiceInstance().suppressAmbientDisplay("test", true);
+ setPluggedIn(true);
+ // Allow asynchronous sandman calls to execute.
+ advanceTime(10000);
+
+ // Verify that forcing dream still works even though ambient display is suppressed
+ forceDream();
+ assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
+ }
+
@Test
public void testSetDozeOverrideFromDreamManager_triggersSuspendBlocker() {
final String suspendBlockerName = "PowerManagerService.Display";
diff --git a/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java b/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java
index e57ad5d9ff8c..24e932f36f80 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java
@@ -57,10 +57,20 @@ public class SafeActivityOptionsTest {
.setLaunchTaskDisplayArea(token)
.setLaunchDisplayId(launchDisplayId)
.setCallerDisplayId(callerDisplayId))
- .selectiveCloneDisplayOptions();
+ .selectiveCloneLaunchOptions();
assertSame(clone.getOriginalOptions().getLaunchTaskDisplayArea(), token);
assertEquals(clone.getOriginalOptions().getLaunchDisplayId(), launchDisplayId);
assertEquals(clone.getOriginalOptions().getCallerDisplayId(), callerDisplayId);
}
+
+ @Test
+ public void test_selectiveCloneLunchRootTask() {
+ final WindowContainerToken token = mock(WindowContainerToken.class);
+ final SafeActivityOptions clone = new SafeActivityOptions(ActivityOptions.makeBasic()
+ .setLaunchRootTask(token))
+ .selectiveCloneLaunchOptions();
+
+ assertSame(clone.getOriginalOptions().getLaunchRootTask(), token);
+ }
}
diff --git a/tools/xmlpersistence/src/main/kotlin/Generator.kt b/tools/xmlpersistence/src/main/kotlin/Generator.kt
index b2c5f4ac767b..8e62388c860f 100644
--- a/tools/xmlpersistence/src/main/kotlin/Generator.kt
+++ b/tools/xmlpersistence/src/main/kotlin/Generator.kt
@@ -149,6 +149,7 @@ private val ClassFieldInfo.allClassFields: List<ClassFieldInfo>
when (field) {
is ClassFieldInfo -> this += field.allClassFields
is ListFieldInfo -> this += field.element.allClassFields
+ else -> {}
}
}
}