Merge "webview: add trace event for relro timeout." into tm-dev
diff --git a/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java b/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
index 517e3ce..31c92ba 100644
--- a/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
@@ -70,6 +70,9 @@
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
ZipFile zf = new ZipFile(mFile);
+ state.pauseTiming();
+ zf.close();
+ state.resumeTiming();
}
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index ae16e01..7141259 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -8260,6 +8260,11 @@
return mMainThread;
}
+ /** @hide */
+ public final ActivityInfo getActivityInfo() {
+ return mActivityInfo;
+ }
+
final void performCreate(Bundle icicle) {
performCreate(icicle, null);
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index b7f1136..0e1a546 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -9263,6 +9263,21 @@
}
/**
+ * Checks if the specified component is the supervision component.
+ * @hide
+ */
+ public boolean isSupervisionComponent(@NonNull ComponentName who) {
+ if (mService != null) {
+ try {
+ return getService().isSupervisionComponent(who);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+ return false;
+ }
+
+ /**
* @hide
* @return the human readable name of the organisation associated with this DPM or {@code null}
* if one is not set.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 6c6a7ca..fea7770 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -178,6 +178,7 @@
boolean setProfileOwner(in ComponentName who, String ownerName, int userHandle);
ComponentName getProfileOwnerAsUser(int userHandle);
ComponentName getProfileOwnerOrDeviceOwnerSupervisionComponent(in UserHandle userHandle);
+ boolean isSupervisionComponent(in ComponentName who);
String getProfileOwnerName(int userHandle);
void setProfileEnabled(in ComponentName who);
void setProfileName(in ComponentName who, String profileName);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 52e64e8..44dc28d 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2618,15 +2618,6 @@
return Build.VERSION_CODES.CUR_DEVELOPMENT;
}
- // STOPSHIP: hack for the pre-release SDK
- if (platformSdkCodenames.length == 0
- && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
- targetCode)) {
- Slog.w(TAG, "Package requires development platform " + targetCode
- + ", returning current version " + Build.VERSION.SDK_INT);
- return Build.VERSION.SDK_INT;
- }
-
// Otherwise, we're looking at an incompatible pre-release SDK.
if (platformSdkCodenames.length > 0) {
outError[0] = "Requires development platform " + targetCode
@@ -2698,15 +2689,6 @@
return Build.VERSION_CODES.CUR_DEVELOPMENT;
}
- // STOPSHIP: hack for the pre-release SDK
- if (platformSdkCodenames.length == 0
- && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
- minCode)) {
- Slog.w(TAG, "Package requires min development platform " + minCode
- + ", returning current version " + Build.VERSION.SDK_INT);
- return Build.VERSION.SDK_INT;
- }
-
// Otherwise, we're looking at an incompatible pre-release SDK.
if (platformSdkCodenames.length > 0) {
outError[0] = "Requires development platform " + minCode
diff --git a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
index 8cc4cdb..3e1c5bb 100644
--- a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
@@ -316,15 +316,6 @@
return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
}
- // STOPSHIP: hack for the pre-release SDK
- if (platformSdkCodenames.length == 0
- && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
- minCode)) {
- Slog.w(TAG, "Parsed package requires min development platform " + minCode
- + ", returning current version " + Build.VERSION.SDK_INT);
- return input.success(Build.VERSION.SDK_INT);
- }
-
// Otherwise, we're looking at an incompatible pre-release SDK.
if (platformSdkCodenames.length > 0) {
return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
@@ -377,27 +368,19 @@
return input.success(targetVers);
}
- // If it's a pre-release SDK and the codename matches this platform, it
- // definitely targets this SDK.
- if (matchTargetCode(platformSdkCodenames, targetCode)) {
- return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
- }
-
- // STOPSHIP: hack for the pre-release SDK
- if (platformSdkCodenames.length == 0
- && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
- targetCode)) {
- Slog.w(TAG, "Parsed package requires development platform " + targetCode
- + ", returning current version " + Build.VERSION.SDK_INT);
- return input.success(Build.VERSION.SDK_INT);
- }
-
try {
if (allowUnknownCodenames && UnboundedSdkLevel.isAtMost(targetCode)) {
return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
}
} catch (IllegalArgumentException e) {
- return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, "Bad package SDK");
+ // isAtMost() throws it when encountering an older SDK codename
+ return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, e.getMessage());
+ }
+
+ // If it's a pre-release SDK and the codename matches this platform, it
+ // definitely targets this SDK.
+ if (matchTargetCode(platformSdkCodenames, targetCode)) {
+ return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
}
// Otherwise, we're looking at an incompatible pre-release SDK.
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index a90eb88..98a8cbd 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -2356,10 +2356,11 @@
* <p>A subset of the available request keys that can be overridden for
* physical devices backing a logical multi-camera.</p>
* <p>This is a subset of android.request.availableRequestKeys which contains a list
- * of keys that can be overridden using {@link CaptureRequest.Builder#setPhysicalCameraKey }.
+ * of keys that can be overridden using
+ * {@link android.hardware.camera2.CaptureRequest.Builder#setPhysicalCameraKey }.
* The respective value of such request key can be obtained by calling
- * {@link CaptureRequest.Builder#getPhysicalCameraKey }. Capture requests that contain
- * individual physical device requests must be built via
+ * {@link android.hardware.camera2.CaptureRequest.Builder#getPhysicalCameraKey }.
+ * Capture requests that contain individual physical device requests must be built via
* {@link android.hardware.camera2.CameraDevice#createCaptureRequest(int, Set)}.</p>
* <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
* <p><b>Limited capability</b> -
@@ -2759,7 +2760,7 @@
* </table>
* <p>For applications targeting SDK version 31 or newer, if the mobile device declares to be
* media performance class 12 or higher by setting
- * {@link android.os.Build.VERSION_CODES.MEDIA_PERFORMANCE_CLASS } to be 31 or larger,
+ * {@link android.os.Build.VERSION#MEDIA_PERFORMANCE_CLASS } to be 31 or larger,
* the primary camera devices (first rear/front camera in the camera ID list) will not
* support JPEG sizes smaller than 1080p. If the application configures a JPEG stream
* smaller than 1080p, the camera device will round up the JPEG image size to at least
@@ -2833,7 +2834,7 @@
* </table>
* <p>For applications targeting SDK version 31 or newer, if the mobile device doesn't declare
* to be media performance class 12 or better by setting
- * {@link android.os.Build.VERSION_CODES.MEDIA_PERFORMANCE_CLASS } to be 31 or larger,
+ * {@link android.os.Build.VERSION#MEDIA_PERFORMANCE_CLASS } to be 31 or larger,
* or if the camera device isn't a primary rear/front camera, the minimum required output
* stream configurations are the same as for applications targeting SDK version older than
* 31.</p>
@@ -2958,9 +2959,27 @@
* can provide.</p>
* <p>Please reference the documentation for the image data destination to
* check if it limits the maximum size for image data.</p>
- * <p>The following table describes the minimum required output stream
- * configurations based on the hardware level
- * ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel}):</p>
+ * <p>For applications targeting SDK version older than 31, the following table
+ * describes the minimum required output stream configurations based on the
+ * hardware level ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel}):
+ * Format | Size | Hardware Level | Notes
+ * :-------------------------------------------------:|:--------------------------------------------:|:--------------:|:--------------:
+ * {@link android.graphics.ImageFormat#JPEG } | {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} (*1) | Any |
+ * {@link android.graphics.ImageFormat#JPEG } | 1920x1080 (1080p) | Any | if 1080p <= activeArraySize
+ * {@link android.graphics.ImageFormat#JPEG } | 1280x720 (720p) | Any | if 720p <= activeArraySize
+ * {@link android.graphics.ImageFormat#JPEG } | 640x480 (480p) | Any | if 480p <= activeArraySize
+ * {@link android.graphics.ImageFormat#JPEG } | 320x240 (240p) | Any | if 240p <= activeArraySize
+ * {@link android.graphics.ImageFormat#YUV_420_888 } | all output sizes available for JPEG | FULL |
+ * {@link android.graphics.ImageFormat#YUV_420_888 } | all output sizes available for JPEG, up to the maximum video size | LIMITED |
+ * {@link android.graphics.ImageFormat#PRIVATE } | same as YUV_420_888 | Any |</p>
+ * <p>For applications targeting SDK version 31 or newer, if the mobile device declares to be
+ * media performance class 12 or higher by setting
+ * {@link android.os.Build.VERSION#MEDIA_PERFORMANCE_CLASS } to be 31 or larger,
+ * the primary camera devices (first rear/front camera in the camera ID list) will not
+ * support JPEG sizes smaller than 1080p. If the application configures a JPEG stream
+ * smaller than 1080p, the camera device will round up the JPEG image size to at least
+ * 1080p. The requirements for IMPLEMENTATION_DEFINED and YUV_420_888 stay the same.
+ * This new minimum required output stream configurations are illustrated by the table below:</p>
* <table>
* <thead>
* <tr>
@@ -2984,32 +3003,38 @@
* <td align="center">if 1080p <= activeArraySize</td>
* </tr>
* <tr>
- * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td>
- * <td align="center">1280x720 (720p)</td>
- * <td align="center">Any</td>
- * <td align="center">if 720p <= activeArraySize</td>
- * </tr>
- * <tr>
- * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td>
- * <td align="center">640x480 (480p)</td>
- * <td align="center">Any</td>
- * <td align="center">if 480p <= activeArraySize</td>
- * </tr>
- * <tr>
- * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td>
- * <td align="center">320x240 (240p)</td>
- * <td align="center">Any</td>
- * <td align="center">if 240p <= activeArraySize</td>
- * </tr>
- * <tr>
* <td align="center">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
- * <td align="center">all output sizes available for JPEG</td>
+ * <td align="center">{@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</td>
* <td align="center">FULL</td>
* <td align="center"></td>
* </tr>
* <tr>
* <td align="center">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
- * <td align="center">all output sizes available for JPEG, up to the maximum video size</td>
+ * <td align="center">1920x1080 (1080p)</td>
+ * <td align="center">FULL</td>
+ * <td align="center">if 1080p <= activeArraySize</td>
+ * </tr>
+ * <tr>
+ * <td align="center">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
+ * <td align="center">1280x720 (720)</td>
+ * <td align="center">FULL</td>
+ * <td align="center">if 720p <= activeArraySize</td>
+ * </tr>
+ * <tr>
+ * <td align="center">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
+ * <td align="center">640x480 (480p)</td>
+ * <td align="center">FULL</td>
+ * <td align="center">if 480p <= activeArraySize</td>
+ * </tr>
+ * <tr>
+ * <td align="center">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
+ * <td align="center">320x240 (240p)</td>
+ * <td align="center">FULL</td>
+ * <td align="center">if 240p <= activeArraySize</td>
+ * </tr>
+ * <tr>
+ * <td align="center">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
+ * <td align="center">all output sizes available for FULL hardware level, up to the maximum video size</td>
* <td align="center">LIMITED</td>
* <td align="center"></td>
* </tr>
@@ -3021,6 +3046,12 @@
* </tr>
* </tbody>
* </table>
+ * <p>For applications targeting SDK version 31 or newer, if the mobile device doesn't declare
+ * to be media performance class 12 or better by setting
+ * {@link android.os.Build.VERSION#MEDIA_PERFORMANCE_CLASS } to be 31 or larger,
+ * or if the camera device isn't a primary rear/front camera, the minimum required output
+ * stream configurations are the same as for applications targeting SDK version older than
+ * 31.</p>
* <p>Refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} and {@link android.hardware.camera2.CameraDevice#createCaptureSession } for additional mandatory
* stream configurations on a per-capability basis.</p>
* <p>*1: For JPEG format, the sizes may be restricted by below conditions:</p>
diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
index cf611fb..0f6010f 100644
--- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
@@ -854,7 +854,7 @@
Class<CaptureRequest.Key<?>> crKeyTyped = (Class<CaptureRequest.Key<?>>) crKey;
ret.addAll(requestChars.getAvailableKeyList(CaptureRequest.class, crKeyTyped,
- requestKeys, /*includeSynthetic*/ false));
+ requestKeys, /*includeSynthetic*/ true));
}
// Jpeg quality and orientation must always be supported
@@ -929,7 +929,7 @@
Class<CaptureResult.Key<?>> crKeyTyped = (Class<CaptureResult.Key<?>>)crKey;
ret.addAll(resultChars.getAvailableKeyList(CaptureResult.class, crKeyTyped,
- resultKeys, /*includeSynthetic*/ false));
+ resultKeys, /*includeSynthetic*/ true));
// Jpeg quality, orientation and sensor timestamp must always be supported
if (!ret.contains(CaptureResult.JPEG_QUALITY)) {
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index b505395..69c6ba9 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -559,18 +559,21 @@
* @see #DISPLAY_CATEGORY_PRESENTATION
*/
public Display[] getDisplays(String category) {
- final int[] displayIds = mGlobal.getDisplayIds();
+ boolean includeDisabledDisplays = (category != null
+ && category.equals(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED));
+ final int[] displayIds = mGlobal.getDisplayIds(includeDisabledDisplays);
synchronized (mLock) {
try {
- if (category == null
- || DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED.equals(category)) {
- addAllDisplaysLocked(mTempDisplays, displayIds);
- } else if (category.equals(DISPLAY_CATEGORY_PRESENTATION)) {
+ if (category != null && category.equals(DISPLAY_CATEGORY_PRESENTATION)) {
addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_WIFI);
addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_EXTERNAL);
addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_OVERLAY);
addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_VIRTUAL);
addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_INTERNAL);
+ } else if ((category == null
+ || DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED.equals(category))) {
+ // All displays requested.
+ addAllDisplaysLocked(mTempDisplays, displayIds);
}
return mTempDisplays.toArray(new Display[mTempDisplays.size()]);
} finally {
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 74356dd..da3a580 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -206,6 +206,16 @@
*/
@UnsupportedAppUsage
public int[] getDisplayIds() {
+ return getDisplayIds(/* includeDisabledDisplays= */ false);
+ }
+
+ /**
+ * Gets all valid logical display ids and invalid ones if specified.
+ *
+ * @return An array containing all display ids.
+ */
+ @UnsupportedAppUsage
+ public int[] getDisplayIds(boolean includeDisabledDisplays) {
try {
synchronized (mLock) {
if (USE_CACHE) {
@@ -214,7 +224,8 @@
}
}
- int[] displayIds = mDm.getDisplayIds();
+ int[] displayIds =
+ mDm.getDisplayIds(includeDisabledDisplays);
if (USE_CACHE) {
mDisplayIdCache = displayIds;
}
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index ca3e580..a4115d1 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -36,7 +36,7 @@
interface IDisplayManager {
@UnsupportedAppUsage
DisplayInfo getDisplayInfo(int displayId);
- int[] getDisplayIds();
+ int[] getDisplayIds(boolean includeDisabled);
boolean isUidPresentOnDisplay(int uid, int displayId);
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index e5dab05..0418a4b 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -31,6 +31,7 @@
import com.android.internal.util.IndentingPrintWriter;
import java.io.Serializable;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Set;
import java.util.function.BiFunction;
@@ -102,7 +103,7 @@
/*
* If mParcelledData is non-null, then mMap will be null and the
* data are stored as a Parcel containing a Bundle. When the data
- * are unparcelled, mParcelledData willbe set to null.
+ * are unparcelled, mParcelledData will be set to null.
*/
@UnsupportedAppUsage
volatile Parcel mParcelledData = null;
@@ -112,6 +113,19 @@
*/
private boolean mParcelledByNative;
+ /*
+ * Flag indicating if mParcelledData is only referenced in this bundle.
+ * mParcelledData could be referenced by other bundles if mMap contains lazy values,
+ * and bundle data is copied to another bundle using putAll or the copy constructors.
+ */
+ boolean mOwnsLazyValues = true;
+
+ /*
+ * As mParcelledData is set to null when it is unparcelled, we keep a weak reference to
+ * it to aid in recycling it. Do not use this reference otherwise.
+ */
+ private WeakReference<Parcel> mWeakParcelledData = null;
+
/**
* The ClassLoader used when unparcelling data from mParcelledData.
*/
@@ -200,6 +214,9 @@
mClassLoader = from.mClassLoader;
if (from.mMap != null) {
+ mOwnsLazyValues = false;
+ from.mOwnsLazyValues = false;
+
if (!deep) {
mMap = new ArrayMap<>(from.mMap);
} else {
@@ -434,6 +451,9 @@
mMap = map;
if (recycleParcel) {
recycleParcel(parcelledData);
+ mWeakParcelledData = null;
+ } else {
+ mWeakParcelledData = new WeakReference<>(parcelledData);
}
mParcelledByNative = false;
mParcelledData = null;
@@ -575,6 +595,10 @@
*/
public void clear() {
unparcel();
+ if (mOwnsLazyValues && mWeakParcelledData != null) {
+ recycleParcel(mWeakParcelledData.get());
+ mWeakParcelledData = null;
+ }
mMap.clear();
}
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index cf28c16..7e355d9 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -301,6 +301,8 @@
public void putAll(Bundle bundle) {
unparcel();
bundle.unparcel();
+ mOwnsLazyValues = false;
+ bundle.mOwnsLazyValues = false;
mMap.putAll(bundle.mMap);
// FD state is now known if and only if both bundles already knew
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 7e264ce..536a0ac 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -41,11 +41,13 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.SystemClock;
+import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceControl.Transaction;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityEmbeddedConnection;
+import android.window.SurfaceSyncer;
import com.android.internal.view.SurfaceCallbackHelper;
@@ -204,6 +206,9 @@
private int mSurfaceFlags = SurfaceControl.HIDDEN;
+ private final SurfaceSyncer mSurfaceSyncer = new SurfaceSyncer();
+ private final ArraySet<Integer> mSyncIds = new ArraySet<>();
+
/**
* Transaction that should be used from the render thread. This transaction is only thread safe
* with other calls directly from the render thread.
@@ -1018,7 +1023,7 @@
if (shouldSyncBuffer) {
handleSyncBufferCallback(callbacks, syncBufferTransactionCallback);
} else {
- redrawNeededAsync(callbacks, this::onDrawFinished);
+ handleSyncNoBuffer(callbacks);
}
}
}
@@ -1061,7 +1066,23 @@
syncBufferCallback.onBufferReady(t);
onDrawFinished();
}));
+ }
+ private void handleSyncNoBuffer(SurfaceHolder.Callback[] callbacks) {
+ final int syncId = mSurfaceSyncer.setupSync(this::onDrawFinished);
+
+ mSurfaceSyncer.addToSync(syncId, syncBufferCallback -> redrawNeededAsync(callbacks,
+ () -> {
+ syncBufferCallback.onBufferReady(null);
+ synchronized (mSyncIds) {
+ mSyncIds.remove(syncId);
+ }
+ }));
+
+ mSurfaceSyncer.markSyncReady(syncId);
+ synchronized (mSyncIds) {
+ mSyncIds.add(syncId);
+ }
}
private void redrawNeededAsync(SurfaceHolder.Callback[] callbacks,
@@ -1070,6 +1091,21 @@
sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
}
+ /**
+ * @hide
+ */
+ @Override
+ public void surfaceSyncStarted() {
+ ViewRootImpl viewRoot = getViewRootImpl();
+ if (viewRoot != null) {
+ synchronized (mSyncIds) {
+ for (int syncId : mSyncIds) {
+ viewRoot.mergeSync(syncId, mSurfaceSyncer);
+ }
+ }
+ }
+ }
+
private static class SyncBufferTransactionCallback {
private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
private Transaction mTransaction;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ad3379f..97e0692 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2019,13 +2019,10 @@
renderer.setStopped(mStopped);
}
if (!mStopped) {
- // Unnecessary to traverse if the window is not yet visible.
- if (getHostVisibility() == View.VISIBLE) {
- // Make sure that relayoutWindow will be called to get valid surface because
- // the previous surface may have been released.
- mAppVisibilityChanged = true;
- scheduleTraversals();
- }
+ // Make sure that relayoutWindow will be called to get valid surface because
+ // the previous surface may have been released.
+ mAppVisibilityChanged = true;
+ scheduleTraversals();
} else {
if (renderer != null) {
renderer.destroyHardwareResources(mView);
@@ -2048,6 +2045,7 @@
void surfaceCreated(Transaction t);
void surfaceReplaced(Transaction t);
void surfaceDestroyed();
+ default void surfaceSyncStarted() {};
}
private final ArrayList<SurfaceChangedCallback> mSurfaceChangedCallbacks = new ArrayList<>();
@@ -2082,6 +2080,12 @@
}
}
+ private void notifySurfaceSyncStarted() {
+ for (int i = 0; i < mSurfaceChangedCallbacks.size(); i++) {
+ mSurfaceChangedCallbacks.get(i).surfaceSyncStarted();
+ }
+ }
+
/**
* @return child layer with the same bounds as its parent {@code mSurface} and cropped to the
* surface insets. If the layer does not exist, it is created.
@@ -3541,6 +3545,7 @@
Log.d(mTag, "Setup new sync id=" + mSyncId);
}
mSurfaceSyncer.addToSync(mSyncId, mSyncTarget);
+ notifySurfaceSyncStarted();
}
private void notifyContentCatpureEvents() {
@@ -10965,4 +10970,11 @@
scheduleTraversals();
}
}
+
+ void mergeSync(int syncId, SurfaceSyncer otherSyncer) {
+ if (!isInLocalSync()) {
+ return;
+ }
+ mSurfaceSyncer.merge(mSyncId, syncId, otherSyncer);
+ }
}
diff --git a/core/java/android/window/SurfaceSyncer.java b/core/java/android/window/SurfaceSyncer.java
index 0e011bb..e6eb071 100644
--- a/core/java/android/window/SurfaceSyncer.java
+++ b/core/java/android/window/SurfaceSyncer.java
@@ -117,13 +117,18 @@
*/
public int setupSync(@NonNull Consumer<Transaction> syncRequestComplete) {
synchronized (mSyncSetLock) {
- mIdCounter++;
+ final int syncId = mIdCounter++;
if (DEBUG) {
- Log.d(TAG, "setupSync " + mIdCounter);
+ Log.d(TAG, "setupSync " + syncId);
}
- SyncSet syncSet = new SyncSet(mIdCounter, syncRequestComplete);
- mSyncSets.put(mIdCounter, syncSet);
- return mIdCounter;
+ SyncSet syncSet = new SyncSet(syncId, transaction -> {
+ synchronized (mSyncSetLock) {
+ mSyncSets.remove(syncId);
+ }
+ syncRequestComplete.accept(transaction);
+ });
+ mSyncSets.put(syncId, syncSet);
+ return syncId;
}
}
@@ -138,7 +143,6 @@
SyncSet syncSet;
synchronized (mSyncSetLock) {
syncSet = mSyncSets.get(syncId);
- mSyncSets.remove(syncId);
}
if (syncSet == null) {
Log.e(TAG, "Failed to find syncSet for syncId=" + syncId);
@@ -148,6 +152,31 @@
}
/**
+ * Merge another SyncSet into the specified syncId.
+ * @param syncId The current syncId to merge into
+ * @param otherSyncId The other syncId to be merged
+ * @param otherSurfaceSyncer The other SurfaceSyncer where the otherSyncId is from
+ */
+ public void merge(int syncId, int otherSyncId, SurfaceSyncer otherSurfaceSyncer) {
+ SyncSet syncSet;
+ synchronized (mSyncSetLock) {
+ syncSet = mSyncSets.get(syncId);
+ }
+
+ SyncSet otherSyncSet = otherSurfaceSyncer.getAndValidateSyncSet(otherSyncId);
+ if (otherSyncSet == null) {
+ return;
+ }
+
+ if (DEBUG) {
+ Log.d(TAG,
+ "merge id=" + otherSyncId + " from=" + otherSurfaceSyncer + " into id=" + syncId
+ + " from" + this);
+ }
+ syncSet.merge(otherSyncSet);
+ }
+
+ /**
* Add a SurfaceView to a sync set. This is different than {@link #addToSync(int, View)} because
* it requires the caller to notify the start and finish drawing in order to sync.
*
@@ -199,8 +228,7 @@
if (DEBUG) {
Log.d(TAG, "addToSync id=" + syncId);
}
- syncSet.addSyncableSurface(syncTarget);
- return true;
+ return syncSet.addSyncableSurface(syncTarget);
}
/**
@@ -284,14 +312,21 @@
private final Set<SyncTarget> mSyncTargets = new ArraySet<>();
private final int mSyncId;
- private final Consumer<Transaction> mSyncRequestCompleteCallback;
+ @GuardedBy("mLock")
+ private Consumer<Transaction> mSyncRequestCompleteCallback;
+
+ @GuardedBy("mLock")
+ private final Set<SyncSet> mMergedSyncSets = new ArraySet<>();
+
+ @GuardedBy("mLock")
+ private boolean mFinished;
private SyncSet(int syncId, Consumer<Transaction> syncRequestComplete) {
mSyncId = syncId;
mSyncRequestCompleteCallback = syncRequestComplete;
}
- void addSyncableSurface(SyncTarget syncTarget) {
+ boolean addSyncableSurface(SyncTarget syncTarget) {
SyncBufferCallback syncBufferCallback = new SyncBufferCallback() {
@Override
public void onBufferReady(Transaction t) {
@@ -306,10 +341,16 @@
};
synchronized (mLock) {
+ if (mSyncReady) {
+ Log.e(TAG, "Sync " + mSyncId + " was already marked as ready. No more "
+ + "SyncTargets can be added.");
+ return false;
+ }
mPendingSyncs.add(syncBufferCallback.hashCode());
mSyncTargets.add(syncTarget);
}
syncTarget.onReadyToSync(syncBufferCallback);
+ return true;
}
void markSyncReady() {
@@ -321,10 +362,11 @@
@GuardedBy("mLock")
private void checkIfSyncIsComplete() {
- if (!mSyncReady || !mPendingSyncs.isEmpty()) {
+ if (!mSyncReady || !mPendingSyncs.isEmpty() || !mMergedSyncSets.isEmpty()) {
if (DEBUG) {
Log.d(TAG, "Syncable is not complete. mSyncReady=" + mSyncReady
- + " mPendingSyncs=" + mPendingSyncs.size());
+ + " mPendingSyncs=" + mPendingSyncs.size() + " mergedSyncs="
+ + mMergedSyncSets.size());
}
return;
}
@@ -338,6 +380,7 @@
}
mSyncTargets.clear();
mSyncRequestCompleteCallback.accept(mTransaction);
+ mFinished = true;
}
/**
@@ -349,6 +392,50 @@
mTransaction.merge(t);
}
}
+
+ public void updateCallback(Consumer<Transaction> transactionConsumer) {
+ synchronized (mLock) {
+ if (mFinished) {
+ Log.e(TAG, "Attempting to merge SyncSet " + mSyncId + " when sync is"
+ + " already complete");
+ transactionConsumer.accept(new Transaction());
+ }
+
+ final Consumer<Transaction> oldCallback = mSyncRequestCompleteCallback;
+ mSyncRequestCompleteCallback = transaction -> {
+ oldCallback.accept(new Transaction());
+ transactionConsumer.accept(transaction);
+ };
+ }
+ }
+
+ /**
+ * Merge a SyncSet into this SyncSet. Since SyncSets could still have pending SyncTargets,
+ * we need to make sure those can still complete before the mergeTo syncSet is considered
+ * complete.
+ *
+ * We keep track of all the merged SyncSets until they are marked as done, and then they
+ * are removed from the set. This SyncSet is not considered done until all the merged
+ * SyncSets are done.
+ *
+ * When the merged SyncSet is complete, it will invoke the original syncRequestComplete
+ * callback but send an empty transaction to ensure the changes are applied early. This
+ * is needed in case the original sync is relying on the callback to continue processing.
+ *
+ * @param otherSyncSet The other SyncSet to merge into this one.
+ */
+ public void merge(SyncSet otherSyncSet) {
+ synchronized (mLock) {
+ mMergedSyncSets.add(otherSyncSet);
+ }
+ otherSyncSet.updateCallback(transaction -> {
+ synchronized (mLock) {
+ mMergedSyncSets.remove(otherSyncSet);
+ mTransaction.merge(transaction);
+ checkIfSyncIsComplete();
+ }
+ });
+ }
}
/**
diff --git a/core/java/android/window/TaskFragmentInfo.java b/core/java/android/window/TaskFragmentInfo.java
index f72164e..56e9107 100644
--- a/core/java/android/window/TaskFragmentInfo.java
+++ b/core/java/android/window/TaskFragmentInfo.java
@@ -23,8 +23,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
+import android.graphics.Rect;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -66,7 +68,7 @@
private final List<IBinder> mActivities = new ArrayList<>();
/** Relative position of the fragment's top left corner in the parent container. */
- private final Point mPositionInParent;
+ private final Point mPositionInParent = new Point();
/**
* Whether the last running activity in the TaskFragment was finished due to clearing task while
@@ -80,21 +82,31 @@
*/
private final boolean mIsTaskFragmentClearedForPip;
+ /**
+ * The maximum {@link ActivityInfo.WindowLayout#minWidth} and
+ * {@link ActivityInfo.WindowLayout#minHeight} aggregated from the TaskFragment's child
+ * activities.
+ */
+ @NonNull
+ private final Point mMinimumDimensions = new Point();
+
/** @hide */
public TaskFragmentInfo(
@NonNull IBinder fragmentToken, @NonNull WindowContainerToken token,
@NonNull Configuration configuration, int runningActivityCount,
boolean isVisible, @NonNull List<IBinder> activities, @NonNull Point positionInParent,
- boolean isTaskClearedForReuse, boolean isTaskFragmentClearedForPip) {
+ boolean isTaskClearedForReuse, boolean isTaskFragmentClearedForPip,
+ @NonNull Point minimumDimensions) {
mFragmentToken = requireNonNull(fragmentToken);
mToken = requireNonNull(token);
mConfiguration.setTo(configuration);
mRunningActivityCount = runningActivityCount;
mIsVisible = isVisible;
mActivities.addAll(activities);
- mPositionInParent = requireNonNull(positionInParent);
+ mPositionInParent.set(positionInParent);
mIsTaskClearedForReuse = isTaskClearedForReuse;
mIsTaskFragmentClearedForPip = isTaskFragmentClearedForPip;
+ mMinimumDimensions.set(minimumDimensions);
}
@NonNull
@@ -154,6 +166,26 @@
}
/**
+ * Returns the minimum width this TaskFragment can be resized to.
+ * Client side must not {@link WindowContainerTransaction#setBounds(WindowContainerToken, Rect)}
+ * that {@link Rect#width()} is shorter than the reported value.
+ * @hide pending unhide
+ */
+ public int getMinimumWidth() {
+ return mMinimumDimensions.x;
+ }
+
+ /**
+ * Returns the minimum width this TaskFragment can be resized to.
+ * Client side must not {@link WindowContainerTransaction#setBounds(WindowContainerToken, Rect)}
+ * that {@link Rect#height()} is shorter than the reported value.
+ * @hide pending unhide
+ */
+ public int getMinimumHeight() {
+ return mMinimumDimensions.y;
+ }
+
+ /**
* Returns {@code true} if the parameters that are important for task fragment organizers are
* equal between this {@link TaskFragmentInfo} and {@param that}.
*/
@@ -170,7 +202,8 @@
&& mActivities.equals(that.mActivities)
&& mPositionInParent.equals(that.mPositionInParent)
&& mIsTaskClearedForReuse == that.mIsTaskClearedForReuse
- && mIsTaskFragmentClearedForPip == that.mIsTaskFragmentClearedForPip;
+ && mIsTaskFragmentClearedForPip == that.mIsTaskFragmentClearedForPip
+ && mMinimumDimensions.equals(that.mMinimumDimensions);
}
private TaskFragmentInfo(Parcel in) {
@@ -180,9 +213,10 @@
mRunningActivityCount = in.readInt();
mIsVisible = in.readBoolean();
in.readBinderList(mActivities);
- mPositionInParent = requireNonNull(in.readTypedObject(Point.CREATOR));
+ mPositionInParent.readFromParcel(in);
mIsTaskClearedForReuse = in.readBoolean();
mIsTaskFragmentClearedForPip = in.readBoolean();
+ mMinimumDimensions.readFromParcel(in);
}
/** @hide */
@@ -194,9 +228,10 @@
dest.writeInt(mRunningActivityCount);
dest.writeBoolean(mIsVisible);
dest.writeBinderList(mActivities);
- dest.writeTypedObject(mPositionInParent, flags);
+ mPositionInParent.writeToParcel(dest, flags);
dest.writeBoolean(mIsTaskClearedForReuse);
dest.writeBoolean(mIsTaskFragmentClearedForPip);
+ mMinimumDimensions.writeToParcel(dest, flags);
}
@NonNull
@@ -224,6 +259,7 @@
+ " positionInParent=" + mPositionInParent
+ " isTaskClearedForReuse=" + mIsTaskClearedForReuse
+ " isTaskFragmentClearedForPip" + mIsTaskFragmentClearedForPip
+ + " minimumDimensions" + mMinimumDimensions
+ "}";
}
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index b7f6a61..bf26568 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -103,6 +103,7 @@
mBg.padding = 0.5f * dp;
mBg.minR = 1 * dp;
layout.setBackground(mBg);
+ layout.setOnLongClickListener(mBg);
setContentView(layout);
}
@@ -291,8 +292,8 @@
return true;
case MotionEvent.ACTION_UP:
- if (mOverrideMinute == 0 && (mOverrideHour % 12) == 0) {
- Log.v(TAG, "12:00 let's gooooo");
+ if (mOverrideMinute == 0 && (mOverrideHour % 12) == 1) {
+ Log.v(TAG, "13:00");
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
launchNextStage(false);
}
@@ -302,18 +303,45 @@
}
}
+ private static final String[][] EMOJI_SETS = {
+ {"🍇", "🍈", "🍉", "🍊", "🍋", "🍌", "🍍", "🥭", "🍎", "🍏", "🍐", "🍑",
+ "🍒", "🍓", "🫐", "🥝"},
+ {"😺", "😸", "😹", "😻", "😼", "😽", "🙀", "😿", "😾"},
+ {"😀", "😃", "😄", "😁", "😆", "😅", "🤣", "😂", "🙂", "🙃", "🫠", "😉", "😊",
+ "😇", "🥰", "😍", "🤩", "😘", "😗", "☺️", "😚", "😙", "🥲", "😋", "😛", "😜",
+ "🤪", "😝", "🤑", "🤗", "🤭", "🫢", "🫣", "🤫", "🤔", "🫡", "🤐", "🤨", "😐",
+ "😑", "😶", "🫥", "😏", "😒", "🙄", "😬", "🤥", "😌", "😔", "😪", "🤤", "😴",
+ "😷"},
+ { "🤩", "😍", "🥰", "😘", "🥳", "🥲", "🥹" },
+ { "🫠" },
+ {"💘", "💝", "💖", "💗", "💓", "💞", "💕", "❣", "💔", "❤", "🧡", "💛",
+ "💚", "💙", "💜", "🤎", "🖤", "🤍"},
+ // {"👁", "️🫦", "👁️"}, // this one is too much
+ {"👽", "🛸", "✨", "🌟", "💫", "🚀", "🪐", "🌙", "⭐", "🌍"},
+ {"🌑", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘"},
+ {"🐙", "🪸", "🦑", "🦀", "🦐", "🐡", "🦞", "🐠", "🐟", "🐳", "🐋", "🐬", "🫧", "🌊",
+ "🦈"},
+ {"🙈", "🙉", "🙊", "🐵", "🐒"},
+ {"♈", "♉", "♊", "♋", "♌", "♍", "♎", "♏", "♐", "♑", "♒", "♓"},
+ {"🕛", "🕧", "🕐", "🕜", "🕑", "🕝", "🕒", "🕞", "🕓", "🕟", "🕔", "🕠", "🕕", "🕡",
+ "🕖", "🕢", "🕗", "🕣", "🕘", "🕤", "🕙", "🕥", "🕚", "🕦"},
+ {"🌺", "🌸", "💮", "🏵️", "🌼", "🌿"},
+ {"🐢", "✨", "🌟", "👑"}
+ };
+
static class Bubble {
public float x, y, r;
public int color;
+ public String text = null;
}
- class BubblesDrawable extends Drawable {
+ class BubblesDrawable extends Drawable implements View.OnLongClickListener {
private static final int MAX_BUBBS = 2000;
private final int[] mColorIds = {
- android.R.color.system_accent1_400,
- android.R.color.system_accent1_500,
- android.R.color.system_accent1_600,
+ android.R.color.system_accent3_400,
+ android.R.color.system_accent3_500,
+ android.R.color.system_accent3_600,
android.R.color.system_accent2_400,
android.R.color.system_accent2_500,
@@ -322,6 +350,8 @@
private int[] mColors = new int[mColorIds.length];
+ private int mEmojiSet = -1;
+
private final Bubble[] mBubbs = new Bubble[MAX_BUBBS];
private int mNumBubbs;
@@ -342,17 +372,34 @@
@Override
public void draw(Canvas canvas) {
+ if (getLevel() == 0) return;
final float f = getLevel() / 10000f;
mPaint.setStyle(Paint.Style.FILL);
+ mPaint.setTextAlign(Paint.Align.CENTER);
int drawn = 0;
for (int j = 0; j < mNumBubbs; j++) {
if (mBubbs[j].color == 0 || mBubbs[j].r == 0) continue;
- mPaint.setColor(mBubbs[j].color);
- canvas.drawCircle(mBubbs[j].x, mBubbs[j].y, mBubbs[j].r * f, mPaint);
+ if (mBubbs[j].text != null) {
+ mPaint.setTextSize(mBubbs[j].r * 1.75f);
+ canvas.drawText(mBubbs[j].text, mBubbs[j].x,
+ mBubbs[j].y + mBubbs[j].r * f * 0.6f, mPaint);
+ } else {
+ mPaint.setColor(mBubbs[j].color);
+ canvas.drawCircle(mBubbs[j].x, mBubbs[j].y, mBubbs[j].r * f, mPaint);
+ }
drawn++;
}
}
+ public void chooseEmojiSet() {
+ mEmojiSet = (int) (Math.random() * EMOJI_SETS.length);
+ final String[] emojiSet = EMOJI_SETS[mEmojiSet];
+ for (int j = 0; j < mBubbs.length; j++) {
+ mBubbs[j].text = emojiSet[(int) (Math.random() * emojiSet.length)];
+ }
+ invalidateSelf();
+ }
+
@Override
protected boolean onLevelChange(int level) {
invalidateSelf();
@@ -423,6 +470,13 @@
public int getOpacity() {
return TRANSLUCENT;
}
+
+ @Override
+ public boolean onLongClick(View v) {
+ if (getLevel() == 0) return false;
+ chooseEmojiSet();
+ return true;
+ }
}
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 36a3c5c..40429c6 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1501,7 +1501,10 @@
: R.string.miniresolver_use_personal_browser);
findViewById(R.id.use_same_profile_browser).setOnClickListener(
- v -> safelyStartActivity(sameProfileResolveInfo));
+ v -> {
+ safelyStartActivity(sameProfileResolveInfo);
+ finish();
+ });
findViewById(R.id.button_open).setOnClickListener(v -> {
Intent intent = otherProfileResolveInfo.getResolvedIntent();
@@ -1510,6 +1513,7 @@
}
safelyStartActivityAsUser(otherProfileResolveInfo,
inactiveAdapter.mResolverListController.getUserHandle());
+ finish();
});
}
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 3436b9e..9b583be 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -113,6 +113,24 @@
final ArrayList<SplitPermissionInfo> mSplitPermissions = new ArrayList<>();
+ private static boolean isAtLeastSdkLevel(String version) {
+ try {
+ return UnboundedSdkLevel.isAtLeast(version);
+ } catch (IllegalArgumentException e) {
+ // UnboundedSdkLevel throws when it sees a known old codename
+ return false;
+ }
+ }
+
+ private static boolean isAtMostSdkLevel(String version) {
+ try {
+ return UnboundedSdkLevel.isAtMost(version);
+ } catch (IllegalArgumentException e) {
+ // UnboundedSdkLevel throws when it sees a known old codename
+ return true;
+ }
+ }
+
public static final class SharedLibraryEntry {
public final String name;
public final String filename;
@@ -180,9 +198,9 @@
// - onBootclasspathBefore is set and we are before that SDK
canBeSafelyIgnored =
(this.onBootclasspathSince != null
- && UnboundedSdkLevel.isAtLeast(this.onBootclasspathSince))
+ && isAtLeastSdkLevel(this.onBootclasspathSince))
|| (this.onBootclasspathBefore != null
- && !UnboundedSdkLevel.isAtLeast(this.onBootclasspathBefore));
+ && !isAtLeastSdkLevel(this.onBootclasspathBefore));
}
}
@@ -885,11 +903,9 @@
+ parser.getPositionDescription());
} else {
boolean allowedMinSdk =
- minDeviceSdk == null || UnboundedSdkLevel.isAtLeast(
- minDeviceSdk);
+ minDeviceSdk == null || isAtLeastSdkLevel(minDeviceSdk);
boolean allowedMaxSdk =
- maxDeviceSdk == null || UnboundedSdkLevel.isAtMost(
- maxDeviceSdk);
+ maxDeviceSdk == null || isAtMostSdkLevel(maxDeviceSdk);
final boolean exists = new File(lfile).exists();
if (allowedMinSdk && allowedMaxSdk && exists) {
String bcpSince = parser.getAttributeValue(null,
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e52da0f..7439b2f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -6628,7 +6628,7 @@
android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.PlatLogoActivity"
- android:theme="@style/Theme.DeviceDefault.Wallpaper.NoTitleBar"
+ android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:icon="@drawable/platlogo"
android:process=":ui">
diff --git a/core/res/res/drawable-nodpi/platlogo.xml b/core/res/res/drawable-nodpi/platlogo.xml
index f816d0c..da21486 100644
--- a/core/res/res/drawable-nodpi/platlogo.xml
+++ b/core/res/res/drawable-nodpi/platlogo.xml
@@ -19,17 +19,27 @@
android:viewportWidth="24"
xmlns:android="http://schemas.android.com/apk/res/android">
<path
- android:pathData="M11 0.51a2.06 2.06 0 0 1 2 0l0.58 0.37a4.15 4.15 0 0 0 2.23 0.55l0.69-0.06a2.07 2.07 0 0 1 1.81 0.95l0.33 0.6a4.14 4.14 0 0 0 1.72 1.52l0.64 0.27a2 2 0 0 1 1.16 1.68l0 0.69A4.12 4.12 0 0 0 23 9.23l0.44 0.53a2.06 2.06 0 0 1 0.24 2l-0.3 0.62a4.14 4.14 0 0 0-0.27 2.28l0.14 0.68a2.08 2.08 0 0 1-0.72 1.91l-0.56 0.41a4 4 0 0 0-1.3 1.89l-0.19 0.66A2.06 2.06 0 0 1 19 21.58l-0.68 0.11a4.09 4.09 0 0 0-2 1.07l-0.48 0.5a2.08 2.08 0 0 1-2 0.49l-0.65-0.23a4.28 4.28 0 0 0-2.3 0l-0.65 0.23a2.08 2.08 0 0 1-2-0.49l-0.48-0.5a4 4 0 0 0-2-1.07L5 21.58A2.06 2.06 0 0 1 3.5 20.23l-0.19-0.66A4 4 0 0 0 2 17.68l-0.56-0.41a2.08 2.08 0 0 1-0.72-1.91l0.14-0.68A4.14 4.14 0 0 0 0.6 12.4l-0.3-0.62a2.06 2.06 0 0 1 0.24-2L1 9.23A4.16 4.16 0 0 0 1.8 7.08l0-0.69A2 2 0 0 1 3 4.71l0.64-0.27A4.14 4.14 0 0 0 5.34 2.92l0.33-0.6a2.07 2.07 0 0 1 1.81-0.95l0.69 0.06A4.15 4.15 0 0 0 10.4 0.88Z"
- android:fillColor="@android:color/system_accent3_400"
+ android:fillColor="@android:color/system_accent1_400"
+ android:pathData="M11,0.3c0.6,-0.3 1.4,-0.3 2,0l0.6,0.4c0.7,0.4 1.4,0.6 2.2,0.6l0.7,-0.1c0.7,0 1.4,0.3 1.8,0.9l0.3,0.6c0.4,0.7 1,1.2 1.7,1.5L21,4.5c0.7,0.3 1.1,0.9 1.2,1.7v0.7C22.2,7.7 22.5,8.4 23,9l0.4,0.5c0.4,0.6 0.5,1.3 0.2,2l-0.3,0.6c-0.3,0.7 -0.4,1.5 -0.3,2.3l0.1,0.7c0.1,0.7 -0.2,1.4 -0.7,1.9L22,17.5c-0.6,0.5 -1.1,1.1 -1.3,1.9L20.5,20c-0.2,0.7 -0.8,1.2 -1.5,1.4l-0.7,0.1c-0.8,0.2 -1.4,0.5 -2,1.1l-0.5,0.5c-0.5,0.5 -1.3,0.7 -2,0.5l-0.6,-0.2c-0.8,-0.2 -1.5,-0.2 -2.3,0l-0.6,0.2c-0.7,0.2 -1.5,0 -2,-0.5l-0.5,-0.5c-0.5,-0.5 -1.2,-0.9 -2,-1.1L5,21.4c-0.7,-0.2 -1.3,-0.7 -1.5,-1.4l-0.2,-0.7C3.1,18.6 2.6,18 2,17.5l-0.6,-0.4c-0.6,-0.5 -0.8,-1.2 -0.7,-1.9l0.1,-0.7c0.1,-0.8 0,-1.6 -0.3,-2.3l-0.3,-0.6c-0.3,-0.7 -0.2,-1.4 0.2,-2L1,9c0.5,-0.6 0.7,-1.4 0.8,-2.2V6.2C1.9,5.5 2.3,4.8 3,4.5l0.6,-0.3c0.7,-0.3 1.3,-0.9 1.7,-1.5l0.3,-0.6c0.4,-0.6 1.1,-1 1.8,-0.9l0.7,0.1c0.8,0 1.6,-0.2 2.2,-0.6L11,0.3z"
/>
<path
- android:pathData="M12.34 6.53h4.05l-2 4.05a3.95 3.95 0 0 1-0.57 7.85 4.1 4.1 0 0 1-1.45-0.27"
- android:strokeColor="@android:color/system_accent1_800"
- android:strokeWidth="2"/>
+ android:pathData="M6.3,6.5l3,0l0,12.2"
+ android:strokeWidth="2.22"
+ android:strokeColor="@android:color/system_accent3_800"
+ />
<path
- android:pathData="M12.34 6.53h4.05l-2 4.05a3.95 3.95 0 0 1-0.57 7.85 4.1 4.1 0 0 1-1.45-0.27"
+ android:pathData="M12.3,6.5h4l-2,4c2.2,0.3 3.6,2.4 3.3,4.5c-0.3,1.9 -1.9,3.3 -3.8,3.3c-0.5,0 -1,-0.1 -1.4,-0.3"
+ android:strokeWidth="2.22"
+ android:strokeColor="@android:color/system_accent3_800"
+ />
+ <path
+ android:pathData="M6.3,6.5l3,0l0,12.2"
+ android:strokeWidth="0.56"
android:strokeColor="@android:color/system_neutral1_100"
- android:strokeWidth="0.5"/>
-
+ />
+ <path
+ android:pathData="M12.3,6.5h4l-2,4c2.2,0.3 3.6,2.4 3.3,4.5c-0.3,1.9 -1.9,3.3 -3.8,3.3c-0.5,0 -1,-0.1 -1.4,-0.3"
+ android:strokeWidth="0.56"
+ android:strokeColor="@android:color/system_neutral1_100"
+ />
</vector>
-
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 608368b..ee8d941 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -307,7 +307,7 @@
<string name="permgroupdesc_sms" msgid="5726462398070064542">"bidali eta ikusi SMS mezuak"</string>
<string name="permgrouplab_storage" msgid="17339216290379241">"Fitxategiak"</string>
<string name="permgroupdesc_storage" msgid="5378659041354582769">"gailuko fitxategiak atzitu"</string>
- <string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"musika eta audioa"</string>
+ <string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"Musika eta audioa"</string>
<string name="permgroupdesc_readMediaAural" msgid="7565467343667089595">"atzitu gailuko musika eta audioak"</string>
<string name="permgrouplab_readMediaVisual" msgid="4724874717811908660">"Argazkiak eta bideoak"</string>
<string name="permgroupdesc_readMediaVisual" msgid="4080463241903508688">"atzitu gailuko argazkiak eta bideoak"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 8cf7e8a..4da0e40 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1611,7 +1611,7 @@
<string name="default_audio_route_category_name" msgid="5241740395748134483">"سیستم"</string>
<string name="bluetooth_a2dp_audio_route_name" msgid="4214648773120426288">"بلوتوثهای صوتی"</string>
<string name="wireless_display_route_description" msgid="8297563323032966831">"صفحه نمایش بیسیم"</string>
- <string name="media_route_button_content_description" msgid="2299223698196869956">"ارسال محتوا"</string>
+ <string name="media_route_button_content_description" msgid="2299223698196869956">"پخش محتوا"</string>
<string name="media_route_chooser_title" msgid="6646594924991269208">"برقراری ارتباط با دستگاه"</string>
<string name="media_route_chooser_title_for_remote_display" msgid="3105906508794326446">"فرستادن محتوای صفحه به دستگاه"</string>
<string name="media_route_chooser_searching" msgid="6119673534251329535">"درحال جستجوی دستگاهها…"</string>
@@ -2039,7 +2039,7 @@
<string name="harmful_app_warning_title" msgid="8794823880881113856">"برنامه مضر شناسایی شد"</string>
<string name="log_access_confirmation_title" msgid="2343578467290592708">"به <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> اجازه میدهید به همه گزارشهای دستگاه دسترسی داشته باشد؟"</string>
<string name="log_access_confirmation_allow" msgid="5302517782599389507">"مجاز کردن دسترسی یکباره"</string>
- <string name="log_access_confirmation_deny" msgid="7685790957455099845">"مجاز نیست"</string>
+ <string name="log_access_confirmation_deny" msgid="7685790957455099845">"اجازه ندادن"</string>
<string name="log_access_confirmation_body" msgid="6581985716241928135">"گزارشهای دستگاه آنچه را در دستگاهتان رخ میدهد ثبت میکند. برنامهها میتوانند از این گزارشها برای پیدا کردن مشکلات و رفع آنها استفاده کنند.\n\nبرخیاز گزارشها ممکن است حاوی اطلاعات حساس باشند، بنابراین فقط به برنامههای مورداعتمادتان اجازه دسترسی به همه گزارشهای دستگاه را بدهید. \n\nاگر به این برنامه اجازه ندهید به همه گزارشهای دستگاه دسترسی داشته باشد، همچنان میتواند به گزارشهای خودش دسترسی داشته باشد. سازنده دستگاه نیز ممکن است همچنان بتواند به برخیاز گزارشها یا اطلاعات دستگاهتان دسترسی داشته باشد. بیشتر بدانید"</string>
<string name="log_access_do_not_show_again" msgid="1058690599083091552">"دوباره نشان داده نشود"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> میخواهد تکههای <xliff:g id="APP_2">%2$s</xliff:g> را نشان دهد"</string>
@@ -2133,7 +2133,7 @@
<string name="resolver_work_tab" msgid="2690019516263167035">"کاری"</string>
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"نمای شخصی"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"نمای کاری"</string>
- <string name="resolver_cross_profile_blocked" msgid="3014597376026044840">"سرپرست سیستم آن را مسدود کرده است"</string>
+ <string name="resolver_cross_profile_blocked" msgid="3014597376026044840">"سرپرست فناوری اطلاعات آن را مسدود کرده است"</string>
<string name="resolver_cant_share_with_work_apps_explanation" msgid="9071442683080586643">"نمیتوان این محتوا را با برنامههای کاری همرسانی کرد"</string>
<string name="resolver_cant_access_work_apps_explanation" msgid="1129960195389373279">"نمیتوان این محتوا را با برنامههای کاری باز کرد"</string>
<string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"نمیتوان این محتوا را با برنامههای شخصی همرسانی کرد"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index c818fec..3ea684e 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1684,7 +1684,7 @@
<string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Кызмат экрандагы нерселерди окуп, аларды башка колдонмолордун үстүнөн көрсөтөт."</string>
<string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Аракеттерди көрүп, аткаруу"</string>
<string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Кызмат колдонмодо жасаган аракеттериңизге же түзмөктүн сенсорлоруна көз салып, сиздин атыңыздан буйруктарды берет."</string>
- <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Уруксат берүү"</string>
+ <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Ооба"</string>
<string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Жок"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Функцияны колдонуп баштоо үчүн аны таптап коюңуз:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Атайын мүмкүнчүлүктөр баскычы менен колдонгуңуз келген функцияларды тандаңыз"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 2c346fd..040f503 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -934,7 +934,7 @@
<string name="lockscreen_transport_stop_description" msgid="1449552232598355348">"Запри"</string>
<string name="lockscreen_transport_rew_description" msgid="7680106856221622779">"Премотај назад"</string>
<string name="lockscreen_transport_ffw_description" msgid="4763794746640196772">"Брзо премотај напред"</string>
- <string name="emergency_calls_only" msgid="3057351206678279851">"Само повици за итни случаи"</string>
+ <string name="emergency_calls_only" msgid="3057351206678279851">"Само итни повици"</string>
<string name="lockscreen_network_locked_message" msgid="2814046965899249635">"Мрежата е заклучена"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="6618356415831082174">"SIM картичката е заклучена со ПУК код."</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"Погледнете го Упатството за корисници или контактирајте со Грижа за корисници."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 5d9275e..b0576b8 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1709,7 +1709,7 @@
<string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"หากต้องการสลับระหว่างฟีเจอร์ต่างๆ ให้ใช้ 3 นิ้วเลื่อนขึ้นแล้วค้างไว้"</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"การขยาย"</string>
<string name="user_switched" msgid="7249833311585228097">"ผู้ใช้ปัจจุบัน <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="user_switching_message" msgid="1912993630661332336">"กำลังเปลี่ยนเป็น <xliff:g id="NAME">%1$s</xliff:g>…"</string>
+ <string name="user_switching_message" msgid="1912993630661332336">"กำลังเปลี่ยนเป็น<xliff:g id="NAME">%1$s</xliff:g>…"</string>
<string name="user_logging_out_message" msgid="7216437629179710359">"กำลังออกจากระบบ <xliff:g id="NAME">%1$s</xliff:g>…"</string>
<string name="owner_name" msgid="8713560351570795743">"เจ้าของ"</string>
<string name="guest_name" msgid="8502103277839834324">"ผู้ใช้ชั่วคราว"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 54c3490..2fc6da8 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -5658,6 +5658,9 @@
<!-- Determines whether SafetyCenter feature is enabled. -->
<bool name="config_enableSafetyCenter">true</bool>
+ <!-- Config for whether Safety Protection is enabled. -->
+ <bool name="config_safetyProtectionEnabled">false</bool>
+
<!-- Flag indicating if help links for Settings app should be enabled. -->
<bool name="config_settingsHelpLinksEnabled">false</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 96e8de0..4e7e20c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4738,6 +4738,8 @@
<java-symbol type="bool" name="config_enableSafetyCenter" />
+ <java-symbol type="bool" name="config_safetyProtectionEnabled" />
+
<java-symbol type="string" name="config_devicePolicyManagementUpdater" />
<java-symbol type="string" name="config_deviceSpecificDeviceStatePolicyProvider" />
diff --git a/graphics/java/android/graphics/Point.java b/graphics/java/android/graphics/Point.java
index 25f76f6..2781ac4b 100644
--- a/graphics/java/android/graphics/Point.java
+++ b/graphics/java/android/graphics/Point.java
@@ -36,8 +36,7 @@
}
public Point(@NonNull Point src) {
- this.x = src.x;
- this.y = src.y;
+ set(src);
}
/**
@@ -49,6 +48,15 @@
}
/**
+ * Sets the point's from {@code src}'s coordinates
+ * @hide
+ */
+ public void set(@NonNull Point src) {
+ this.x = src.x;
+ this.y = src.y;
+ }
+
+ /**
* Negate the point's coordinates
*/
public final void negate() {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
index 44af1a9..f09a910 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
@@ -18,6 +18,8 @@
import android.annotation.NonNull;
import android.app.Activity;
+import android.util.Pair;
+import android.util.Size;
/**
* Client-side descriptor of a split that holds two containers.
@@ -66,6 +68,13 @@
return mSplitRule;
}
+ /** Returns the minimum dimension pair of primary container and secondary container. */
+ @NonNull
+ Pair<Size, Size> getMinDimensionsPair() {
+ return new Pair<>(mPrimaryContainer.getMinDimensions(),
+ mSecondaryContainer.getMinDimensions());
+ }
+
boolean isPlaceholderContainer() {
return (mSplitRule instanceof SplitPlaceholderRule);
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 575c3f0..0ed23cb9 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -24,9 +24,11 @@
import static androidx.window.extensions.embedding.SplitContainer.isStickyPlaceholderRule;
import static androidx.window.extensions.embedding.SplitContainer.shouldFinishAssociatedContainerWhenAdjacent;
import static androidx.window.extensions.embedding.SplitContainer.shouldFinishAssociatedContainerWhenStacked;
+import static androidx.window.extensions.embedding.SplitPresenter.boundsSmallerThanMinDimensions;
+import static androidx.window.extensions.embedding.SplitPresenter.getActivityIntentMinDimensionsPair;
+import static androidx.window.extensions.embedding.SplitPresenter.getMinDimensions;
+import static androidx.window.extensions.embedding.SplitPresenter.shouldShowSideBySide;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityClient;
import android.app.ActivityOptions;
@@ -43,11 +45,15 @@
import android.os.Looper;
import android.util.ArraySet;
import android.util.Log;
+import android.util.Pair;
+import android.util.Size;
import android.util.SparseArray;
import android.window.TaskFragmentInfo;
import android.window.WindowContainerTransaction;
import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
import com.android.internal.annotations.VisibleForTesting;
@@ -63,7 +69,7 @@
*/
public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmentCallback,
ActivityEmbeddingComponent {
- private static final String TAG = "SplitController";
+ static final String TAG = "SplitController";
@VisibleForTesting
@GuardedBy("mLock")
@@ -350,7 +356,7 @@
if (!(rule instanceof SplitRule)) {
continue;
}
- if (mPresenter.shouldShowSideBySide(taskContainer.getTaskBounds(), (SplitRule) rule)) {
+ if (shouldShowSideBySide(taskContainer.getTaskBounds(), (SplitRule) rule)) {
return true;
}
}
@@ -614,12 +620,16 @@
// Can launch in the existing secondary container if the rules share the same
// presentation.
final TaskFragmentContainer secondaryContainer = splitContainer.getSecondaryContainer();
- if (secondaryContainer == getContainerWithActivity(secondaryActivity)) {
+ if (secondaryContainer == getContainerWithActivity(secondaryActivity)
+ && !boundsSmallerThanMinDimensions(secondaryContainer.getLastRequestedBounds(),
+ getMinDimensions(secondaryActivity))) {
// The activity is already in the target TaskFragment.
return true;
}
secondaryContainer.addPendingAppearedActivity(secondaryActivity);
final WindowContainerTransaction wct = new WindowContainerTransaction();
+ mPresenter.expandSplitContainerIfNeeded(wct, splitContainer, primaryActivity,
+ secondaryActivity, null /* secondaryIntent */);
wct.reparentActivityToTaskFragment(
secondaryContainer.getTaskFragmentToken(),
secondaryActivity.getActivityToken());
@@ -791,6 +801,8 @@
&& (canReuseContainer(splitRule, splitContainer.getSplitRule())
// TODO(b/231845476) we should always respect clearTop.
|| !respectClearTop)) {
+ mPresenter.expandSplitContainerIfNeeded(wct, splitContainer, primaryActivity,
+ null /* secondaryActivity */, intent);
// Can launch in the existing secondary container if the rules share the same
// presentation.
return splitContainer.getSecondaryContainer();
@@ -1117,8 +1129,16 @@
// Check if there is enough space for launch
final SplitPlaceholderRule placeholderRule = getPlaceholderRule(activity);
- if (placeholderRule == null || !mPresenter.shouldShowSideBySide(
- mPresenter.getParentContainerBounds(activity), placeholderRule)) {
+
+ if (placeholderRule == null) {
+ return false;
+ }
+
+ final Pair<Size, Size> minDimensionsPair = getActivityIntentMinDimensionsPair(activity,
+ placeholderRule.getPlaceholderIntent());
+ if (!shouldShowSideBySide(
+ mPresenter.getParentContainerBounds(activity), placeholderRule,
+ minDimensionsPair)) {
return false;
}
@@ -1161,7 +1181,7 @@
return false;
}
- if (mPresenter.shouldShowSideBySide(splitContainer)) {
+ if (shouldShowSideBySide(splitContainer)) {
return false;
}
@@ -1233,7 +1253,7 @@
// Splits that are not showing side-by-side are reported as having 0 split
// ratio, since by definition in the API the primary container occupies no
// width of the split when covered by the secondary.
- mPresenter.shouldShowSideBySide(container)
+ shouldShowSideBySide(container)
? container.getSplitRule().getSplitRatio()
: 0.0f);
splitStates.add(splitState);
@@ -1402,7 +1422,7 @@
}
// Decide whether the associated container should be retained based on the current
// presentation mode.
- if (mPresenter.shouldShowSideBySide(splitContainer)) {
+ if (shouldShowSideBySide(splitContainer)) {
return !shouldFinishAssociatedContainerWhenAdjacent(finishBehavior);
} else {
return !shouldFinishAssociatedContainerWhenStacked(finishBehavior);
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index ac3b05a..63be98e 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -16,15 +16,23 @@
package androidx.window.extensions.embedding;
+import static android.content.pm.PackageManager.MATCH_ALL;
+
import android.app.Activity;
+import android.app.ActivityThread;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration.WindowingMode;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
import android.util.LayoutDirection;
+import android.util.Pair;
+import android.util.Size;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowMetrics;
@@ -34,6 +42,8 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.concurrent.Executor;
/**
@@ -41,9 +51,12 @@
* {@link SplitController}.
*/
class SplitPresenter extends JetpackTaskFragmentOrganizer {
- private static final int POSITION_START = 0;
- private static final int POSITION_END = 1;
- private static final int POSITION_FILL = 2;
+ @VisibleForTesting
+ static final int POSITION_START = 0;
+ @VisibleForTesting
+ static final int POSITION_END = 1;
+ @VisibleForTesting
+ static final int POSITION_FILL = 2;
@IntDef(value = {
POSITION_START,
@@ -103,8 +116,10 @@
@NonNull WindowContainerTransaction wct, @NonNull Activity primaryActivity,
@NonNull Intent secondaryIntent, @NonNull SplitPairRule rule) {
final Rect parentBounds = getParentContainerBounds(primaryActivity);
+ final Pair<Size, Size> minDimensionsPair = getActivityIntentMinDimensionsPair(
+ primaryActivity, secondaryIntent);
final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule,
- isLtr(primaryActivity, rule));
+ primaryActivity, minDimensionsPair);
final TaskFragmentContainer primaryContainer = prepareContainerForActivity(wct,
primaryActivity, primaryRectBounds, null);
@@ -113,7 +128,7 @@
final TaskFragmentContainer secondaryContainer = mController.newContainer(
secondaryIntent, primaryActivity, taskId);
final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds,
- rule, isLtr(primaryActivity, rule));
+ rule, primaryActivity, minDimensionsPair);
final int windowingMode = mController.getTaskContainer(taskId)
.getWindowingModeForSplitTaskFragment(secondaryRectBounds);
createTaskFragment(wct, secondaryContainer.getTaskFragmentToken(),
@@ -121,7 +136,8 @@
windowingMode);
// Set adjacent to each other so that the containers below will be invisible.
- setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule);
+ setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule,
+ minDimensionsPair);
mController.registerSplit(wct, primaryContainer, primaryActivity, secondaryContainer, rule);
@@ -144,13 +160,15 @@
final WindowContainerTransaction wct = new WindowContainerTransaction();
final Rect parentBounds = getParentContainerBounds(primaryActivity);
+ final Pair<Size, Size> minDimensionsPair = getActivitiesMinDimensionsPair(primaryActivity,
+ secondaryActivity);
final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule,
- isLtr(primaryActivity, rule));
+ primaryActivity, minDimensionsPair);
final TaskFragmentContainer primaryContainer = prepareContainerForActivity(wct,
primaryActivity, primaryRectBounds, null);
final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds, rule,
- isLtr(primaryActivity, rule));
+ primaryActivity, minDimensionsPair);
final TaskFragmentContainer curSecondaryContainer = mController.getContainerWithActivity(
secondaryActivity);
TaskFragmentContainer containerToAvoid = primaryContainer;
@@ -162,7 +180,8 @@
secondaryActivity, secondaryRectBounds, containerToAvoid);
// Set adjacent to each other so that the containers below will be invisible.
- setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule);
+ setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule,
+ minDimensionsPair);
mController.registerSplit(wct, primaryContainer, primaryActivity, secondaryContainer, rule);
@@ -211,10 +230,12 @@
void startActivityToSide(@NonNull Activity launchingActivity, @NonNull Intent activityIntent,
@Nullable Bundle activityOptions, @NonNull SplitRule rule, boolean isPlaceholder) {
final Rect parentBounds = getParentContainerBounds(launchingActivity);
+ final Pair<Size, Size> minDimensionsPair = getActivityIntentMinDimensionsPair(
+ launchingActivity, activityIntent);
final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule,
- isLtr(launchingActivity, rule));
+ launchingActivity, minDimensionsPair);
final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds, rule,
- isLtr(launchingActivity, rule));
+ launchingActivity, minDimensionsPair);
TaskFragmentContainer primaryContainer = mController.getContainerWithActivity(
launchingActivity);
@@ -258,11 +279,11 @@
if (activity == null) {
return;
}
- final boolean isLtr = isLtr(activity, rule);
+ final Pair<Size, Size> minDimensionsPair = splitContainer.getMinDimensionsPair();
final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule,
- isLtr);
+ activity, minDimensionsPair);
final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds, rule,
- isLtr);
+ activity, minDimensionsPair);
final TaskFragmentContainer secondaryContainer = splitContainer.getSecondaryContainer();
// Whether the placeholder is becoming side-by-side with the primary from fullscreen.
final boolean isPlaceholderBecomingSplit = splitContainer.isPlaceholderContainer()
@@ -273,7 +294,8 @@
// are created again.
resizeTaskFragmentIfRegistered(wct, primaryContainer, primaryRectBounds);
resizeTaskFragmentIfRegistered(wct, secondaryContainer, secondaryRectBounds);
- setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule);
+ setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule,
+ minDimensionsPair);
if (isPlaceholderBecomingSplit) {
// When placeholder is shown in split, we should keep the focus on the primary.
wct.requestFocusOnTaskFragment(primaryContainer.getTaskFragmentToken());
@@ -287,11 +309,12 @@
private void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
@NonNull TaskFragmentContainer primaryContainer,
- @NonNull TaskFragmentContainer secondaryContainer, @NonNull SplitRule splitRule) {
+ @NonNull TaskFragmentContainer secondaryContainer, @NonNull SplitRule splitRule,
+ @NonNull Pair<Size, Size> minDimensionsPair) {
final Rect parentBounds = getParentContainerBounds(primaryContainer);
// Clear adjacent TaskFragments if the container is shown in fullscreen, or the
// secondaryContainer could not be finished.
- if (!shouldShowSideBySide(parentBounds, splitRule)) {
+ if (!shouldShowSideBySide(parentBounds, splitRule, minDimensionsPair)) {
setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(),
null /* secondary */, null /* splitRule */);
} else {
@@ -373,41 +396,160 @@
super.updateWindowingMode(wct, fragmentToken, windowingMode);
}
- boolean shouldShowSideBySide(@NonNull SplitContainer splitContainer) {
- final Rect parentBounds = getParentContainerBounds(splitContainer.getPrimaryContainer());
- return shouldShowSideBySide(parentBounds, splitContainer.getSplitRule());
+ /**
+ * Expands the split container if the current split bounds are smaller than the Activity or
+ * Intent that is added to the container.
+ */
+ void expandSplitContainerIfNeeded(@NonNull WindowContainerTransaction wct,
+ @NonNull SplitContainer splitContainer, @NonNull Activity primaryActivity,
+ @Nullable Activity secondaryActivity, @Nullable Intent secondaryIntent) {
+ if (secondaryActivity == null && secondaryIntent == null) {
+ throw new IllegalArgumentException("Either secondaryActivity or secondaryIntent must be"
+ + " non-null.");
+ }
+ final Rect taskBounds = getTaskBoundsFromActivity(primaryActivity);
+ final Pair<Size, Size> minDimensionsPair;
+ if (secondaryActivity != null) {
+ minDimensionsPair = getActivitiesMinDimensionsPair(primaryActivity, secondaryActivity);
+ } else {
+ minDimensionsPair = getActivityIntentMinDimensionsPair(primaryActivity,
+ secondaryIntent);
+ }
+ // Expand the splitContainer if minimum dimensions are not satisfied.
+ if (!shouldShowSideBySide(taskBounds, splitContainer.getSplitRule(), minDimensionsPair)) {
+ expandTaskFragment(wct, splitContainer.getPrimaryContainer()
+ .getTaskFragmentToken());
+ expandTaskFragment(wct, splitContainer.getSecondaryContainer()
+ .getTaskFragmentToken());
+ }
}
- boolean shouldShowSideBySide(@Nullable Rect parentBounds, @NonNull SplitRule rule) {
+ static boolean shouldShowSideBySide(@NonNull Rect parentBounds, @NonNull SplitRule rule) {
+ return shouldShowSideBySide(parentBounds, rule, null /* minimumDimensionPair */);
+ }
+
+ static boolean shouldShowSideBySide(@NonNull SplitContainer splitContainer) {
+ final Rect parentBounds = getParentContainerBounds(splitContainer.getPrimaryContainer());
+
+ return shouldShowSideBySide(parentBounds, splitContainer.getSplitRule(),
+ splitContainer.getMinDimensionsPair());
+ }
+
+ static boolean shouldShowSideBySide(@NonNull Rect parentBounds, @NonNull SplitRule rule,
+ @Nullable Pair<Size, Size> minDimensionsPair) {
// TODO(b/190433398): Supply correct insets.
final WindowMetrics parentMetrics = new WindowMetrics(parentBounds,
new WindowInsets(new Rect()));
- return rule.checkParentMetrics(parentMetrics);
+ // Don't show side by side if bounds is not qualified.
+ if (!rule.checkParentMetrics(parentMetrics)) {
+ return false;
+ }
+ final float splitRatio = rule.getSplitRatio();
+ // We only care the size of the bounds regardless of its position.
+ final Rect primaryBounds = getPrimaryBounds(parentBounds, splitRatio, true /* isLtr */);
+ final Rect secondaryBounds = getSecondaryBounds(parentBounds, splitRatio, true /* isLtr */);
+
+ if (minDimensionsPair == null) {
+ return true;
+ }
+ return !boundsSmallerThanMinDimensions(primaryBounds, minDimensionsPair.first)
+ && !boundsSmallerThanMinDimensions(secondaryBounds, minDimensionsPair.second);
}
@NonNull
- private Rect getBoundsForPosition(@Position int position, @NonNull Rect parentBounds,
- @NonNull SplitRule rule, boolean isLtr) {
- if (!shouldShowSideBySide(parentBounds, rule)) {
- return new Rect();
- }
-
- final float splitRatio = rule.getSplitRatio();
- final float rtlSplitRatio = 1 - splitRatio;
- switch (position) {
- case POSITION_START:
- return isLtr ? getLeftContainerBounds(parentBounds, splitRatio)
- : getRightContainerBounds(parentBounds, rtlSplitRatio);
- case POSITION_END:
- return isLtr ? getRightContainerBounds(parentBounds, splitRatio)
- : getLeftContainerBounds(parentBounds, rtlSplitRatio);
- case POSITION_FILL:
- return parentBounds;
- }
- return parentBounds;
+ static Pair<Size, Size> getActivitiesMinDimensionsPair(Activity primaryActivity,
+ Activity secondaryActivity) {
+ return new Pair<>(getMinDimensions(primaryActivity), getMinDimensions(secondaryActivity));
}
- private Rect getLeftContainerBounds(@NonNull Rect parentBounds, float splitRatio) {
+ @NonNull
+ static Pair<Size, Size> getActivityIntentMinDimensionsPair(Activity primaryActivity,
+ Intent secondaryIntent) {
+ return new Pair<>(getMinDimensions(primaryActivity), getMinDimensions(secondaryIntent));
+ }
+
+ @Nullable
+ static Size getMinDimensions(@Nullable Activity activity) {
+ if (activity == null) {
+ return null;
+ }
+ final ActivityInfo.WindowLayout windowLayout = activity.getActivityInfo().windowLayout;
+ if (windowLayout == null) {
+ return null;
+ }
+ return new Size(windowLayout.minWidth, windowLayout.minHeight);
+ }
+
+ // TODO(b/232871351): find a light-weight approach for this check.
+ @Nullable
+ static Size getMinDimensions(@Nullable Intent intent) {
+ if (intent == null) {
+ return null;
+ }
+ final PackageManager packageManager = ActivityThread.currentActivityThread()
+ .getApplication().getPackageManager();
+ final ResolveInfo resolveInfo = packageManager.resolveActivity(intent,
+ PackageManager.ResolveInfoFlags.of(MATCH_ALL));
+ if (resolveInfo == null) {
+ return null;
+ }
+ final ActivityInfo activityInfo = resolveInfo.activityInfo;
+ if (activityInfo == null) {
+ return null;
+ }
+ final ActivityInfo.WindowLayout windowLayout = activityInfo.windowLayout;
+ if (windowLayout == null) {
+ return null;
+ }
+ return new Size(windowLayout.minWidth, windowLayout.minHeight);
+ }
+
+ static boolean boundsSmallerThanMinDimensions(@NonNull Rect bounds,
+ @Nullable Size minDimensions) {
+ if (minDimensions == null) {
+ return false;
+ }
+ return bounds.width() < minDimensions.getWidth()
+ || bounds.height() < minDimensions.getHeight();
+ }
+
+ @VisibleForTesting
+ @NonNull
+ static Rect getBoundsForPosition(@Position int position, @NonNull Rect parentBounds,
+ @NonNull SplitRule rule, @NonNull Activity primaryActivity,
+ @Nullable Pair<Size, Size> minDimensionsPair) {
+ if (!shouldShowSideBySide(parentBounds, rule, minDimensionsPair)) {
+ return new Rect();
+ }
+ final boolean isLtr = isLtr(primaryActivity, rule);
+ final float splitRatio = rule.getSplitRatio();
+
+ switch (position) {
+ case POSITION_START:
+ return getPrimaryBounds(parentBounds, splitRatio, isLtr);
+ case POSITION_END:
+ return getSecondaryBounds(parentBounds, splitRatio, isLtr);
+ case POSITION_FILL:
+ default:
+ return new Rect();
+ }
+ }
+
+ @NonNull
+ private static Rect getPrimaryBounds(@NonNull Rect parentBounds, float splitRatio,
+ boolean isLtr) {
+ return isLtr ? getLeftContainerBounds(parentBounds, splitRatio)
+ : getRightContainerBounds(parentBounds, 1 - splitRatio);
+ }
+
+ @NonNull
+ private static Rect getSecondaryBounds(@NonNull Rect parentBounds, float splitRatio,
+ boolean isLtr) {
+ return isLtr ? getRightContainerBounds(parentBounds, splitRatio)
+ : getLeftContainerBounds(parentBounds, 1 - splitRatio);
+ }
+
+ private static Rect getLeftContainerBounds(@NonNull Rect parentBounds, float splitRatio) {
return new Rect(
parentBounds.left,
parentBounds.top,
@@ -415,7 +557,7 @@
parentBounds.bottom);
}
- private Rect getRightContainerBounds(@NonNull Rect parentBounds, float splitRatio) {
+ private static Rect getRightContainerBounds(@NonNull Rect parentBounds, float splitRatio) {
return new Rect(
(int) (parentBounds.left + parentBounds.width() * splitRatio),
parentBounds.top,
@@ -427,7 +569,7 @@
* Checks if a split with the provided rule should be displays in left-to-right layout
* direction, either always or with the current configuration.
*/
- private boolean isLtr(@NonNull Context context, @NonNull SplitRule rule) {
+ private static boolean isLtr(@NonNull Context context, @NonNull SplitRule rule) {
switch (rule.getLayoutDirection()) {
case LayoutDirection.LOCALE:
return context.getResources().getConfiguration().getLayoutDirection()
@@ -441,7 +583,7 @@
}
@NonNull
- Rect getParentContainerBounds(@NonNull TaskFragmentContainer container) {
+ static Rect getParentContainerBounds(@NonNull TaskFragmentContainer container) {
return container.getTaskContainer().getTaskBounds();
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index 624cde5..abf32a2 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -26,6 +26,7 @@
import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
+import android.util.Size;
import android.window.TaskFragmentInfo;
import android.window.WindowContainerTransaction;
@@ -414,6 +415,11 @@
}
}
+ @NonNull
+ Rect getLastRequestedBounds() {
+ return mLastRequestedBounds;
+ }
+
/**
* Checks if last requested windowing mode is equal to the provided value.
*/
@@ -439,6 +445,31 @@
return mTaskContainer;
}
+ @Nullable
+ Size getMinDimensions() {
+ if (mInfo == null) {
+ return null;
+ }
+ int maxMinWidth = mInfo.getMinimumWidth();
+ int maxMinHeight = mInfo.getMinimumHeight();
+ for (Activity activity : mPendingAppearedActivities) {
+ final Size minDimensions = SplitPresenter.getMinDimensions(activity);
+ if (minDimensions == null) {
+ continue;
+ }
+ maxMinWidth = Math.max(maxMinWidth, minDimensions.getWidth());
+ maxMinHeight = Math.max(maxMinHeight, minDimensions.getHeight());
+ }
+ if (mPendingAppearedIntent != null) {
+ final Size minDimensions = SplitPresenter.getMinDimensions(mPendingAppearedIntent);
+ if (minDimensions != null) {
+ maxMinWidth = Math.max(maxMinWidth, minDimensions.getWidth());
+ maxMinHeight = Math.max(maxMinHeight, minDimensions.getHeight());
+ }
+ }
+ return new Size(maxMinWidth, maxMinHeight);
+ }
+
@Override
public String toString() {
return toString(true /* includeContainersToFinishOnExit */);
diff --git a/libs/WindowManager/Jetpack/tests/unittest/AndroidManifest.xml b/libs/WindowManager/Jetpack/tests/unittest/AndroidManifest.xml
index b12b6f6..c736e9e 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/AndroidManifest.xml
+++ b/libs/WindowManager/Jetpack/tests/unittest/AndroidManifest.xml
@@ -22,6 +22,11 @@
<application android:debuggable="true" android:largeHeap="true">
<uses-library android:name="android.test.mock" />
<uses-library android:name="android.test.runner" />
+
+ <activity android:name="androidx.window.extensions.embedding.MinimumDimensionActivity">
+ <layout android:minWidth="600px"
+ android:minHeight="1200px"/>
+ </activity>
</application>
<instrumentation
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
new file mode 100644
index 0000000..3ef3281
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.extensions.embedding;
+
+import static androidx.window.extensions.embedding.SplitRule.FINISH_ALWAYS;
+import static androidx.window.extensions.embedding.SplitRule.FINISH_NEVER;
+
+import static org.mockito.Mockito.mock;
+
+import android.annotation.NonNull;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.util.Pair;
+import android.window.TaskFragmentInfo;
+import android.window.WindowContainerToken;
+
+import java.util.Collections;
+
+public class EmbeddingTestUtils {
+ static final Rect TASK_BOUNDS = new Rect(0, 0, 600, 1200);
+ static final int TASK_ID = 10;
+ static final float SPLIT_RATIO = 0.5f;
+ /** Default finish behavior in Jetpack. */
+ static final int DEFAULT_FINISH_PRIMARY_WITH_SECONDARY = FINISH_NEVER;
+ static final int DEFAULT_FINISH_SECONDARY_WITH_PRIMARY = FINISH_ALWAYS;
+
+ private EmbeddingTestUtils() {}
+
+ /** Gets the bounds of a TaskFragment that is in split. */
+ static Rect getSplitBounds(boolean isPrimary) {
+ final int width = (int) (TASK_BOUNDS.width() * SPLIT_RATIO);
+ return isPrimary
+ ? new Rect(TASK_BOUNDS.left, TASK_BOUNDS.top, TASK_BOUNDS.left + width,
+ TASK_BOUNDS.bottom)
+ : new Rect(
+ TASK_BOUNDS.left + width, TASK_BOUNDS.top, TASK_BOUNDS.right,
+ TASK_BOUNDS.bottom);
+ }
+
+ /** Creates a rule to always split the given activity and the given intent. */
+ static SplitRule createSplitRule(@NonNull Activity primaryActivity,
+ @NonNull Intent secondaryIntent) {
+ final Pair<Activity, Intent> targetPair = new Pair<>(primaryActivity, secondaryIntent);
+ return new SplitPairRule.Builder(
+ activityPair -> false,
+ targetPair::equals,
+ w -> true)
+ .setSplitRatio(SPLIT_RATIO)
+ .setShouldClearTop(true)
+ .build();
+ }
+
+ /** Creates a rule to always split the given activities. */
+ static SplitRule createSplitRule(@NonNull Activity primaryActivity,
+ @NonNull Activity secondaryActivity) {
+ return createSplitRule(primaryActivity, secondaryActivity,
+ DEFAULT_FINISH_PRIMARY_WITH_SECONDARY, DEFAULT_FINISH_SECONDARY_WITH_PRIMARY,
+ true /* clearTop */);
+ }
+
+ /** Creates a rule to always split the given activities with the given finish behaviors. */
+ static SplitRule createSplitRule(@NonNull Activity primaryActivity,
+ @NonNull Activity secondaryActivity, int finishPrimaryWithSecondary,
+ int finishSecondaryWithPrimary, boolean clearTop) {
+ final Pair<Activity, Activity> targetPair = new Pair<>(primaryActivity, secondaryActivity);
+ return new SplitPairRule.Builder(
+ targetPair::equals,
+ activityIntentPair -> false,
+ w -> true)
+ .setSplitRatio(SPLIT_RATIO)
+ .setFinishPrimaryWithSecondary(finishPrimaryWithSecondary)
+ .setFinishSecondaryWithPrimary(finishSecondaryWithPrimary)
+ .setShouldClearTop(clearTop)
+ .build();
+ }
+
+ /** Creates a mock TaskFragmentInfo for the given TaskFragment. */
+ static TaskFragmentInfo createMockTaskFragmentInfo(@NonNull TaskFragmentContainer container,
+ @NonNull Activity activity) {
+ return new TaskFragmentInfo(container.getTaskFragmentToken(),
+ mock(WindowContainerToken.class),
+ new Configuration(),
+ 1,
+ true /* isVisible */,
+ Collections.singletonList(activity.getActivityToken()),
+ new Point(),
+ false /* isTaskClearedForReuse */,
+ false /* isTaskFragmentClearedForPip */,
+ new Point());
+ }
+
+ static ActivityInfo createActivityInfoWithMinDimensions() {
+ ActivityInfo aInfo = new ActivityInfo();
+ final Rect primaryBounds = getSplitBounds(true /* isPrimary */);
+ aInfo.windowLayout = new ActivityInfo.WindowLayout(0, 0, 0, 0, 0,
+ primaryBounds.width() + 1, primaryBounds.height() + 1);
+ return aInfo;
+ }
+}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
index a191e68..4d25952 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
@@ -18,6 +18,8 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -58,8 +60,6 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class JetpackTaskFragmentOrganizerTest {
- private static final int TASK_ID = 10;
-
@Mock
private WindowContainerTransaction mTransaction;
@Mock
@@ -131,6 +131,7 @@
return new TaskFragmentInfo(container.getTaskFragmentToken(),
mock(WindowContainerToken.class), new Configuration(), 0 /* runningActivityCount */,
false /* isVisible */, new ArrayList<>(), new Point(),
- false /* isTaskClearedForReuse */, false /* isTaskFragmentClearedForPip */);
+ false /* isTaskClearedForReuse */, false /* isTaskFragmentClearedForPip */,
+ new Point());
}
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/MinimumDimensionActivity.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/MinimumDimensionActivity.java
new file mode 100644
index 0000000..ffcaf3e
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/MinimumDimensionActivity.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.extensions.embedding;
+
+import android.app.Activity;
+
+/**
+ * Activity that declares minWidth and minHeight in
+ * {@link android.content.pm.ActivityInfo.WindowLayout}
+ */
+public class MinimumDimensionActivity extends Activity {}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index 60390eb..982ab804 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
@@ -19,8 +19,14 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.SPLIT_RATIO;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_BOUNDS;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createActivityInfoWithMinDimensions;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createMockTaskFragmentInfo;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitRule;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.getSplitBounds;
import static androidx.window.extensions.embedding.SplitRule.FINISH_ALWAYS;
-import static androidx.window.extensions.embedding.SplitRule.FINISH_NEVER;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -49,20 +55,19 @@
import android.app.ActivityOptions;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
-import android.util.Pair;
import android.window.TaskFragmentInfo;
-import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
+import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -86,16 +91,9 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class SplitControllerTest {
- private static final int TASK_ID = 10;
- private static final Rect TASK_BOUNDS = new Rect(0, 0, 600, 1200);
- private static final float SPLIT_RATIO = 0.5f;
private static final Intent PLACEHOLDER_INTENT = new Intent().setComponent(
new ComponentName("test", "placeholder"));
- /** Default finish behavior in Jetpack. */
- private static final int DEFAULT_FINISH_PRIMARY_WITH_SECONDARY = FINISH_NEVER;
- private static final int DEFAULT_FINISH_SECONDARY_WITH_PRIMARY = FINISH_ALWAYS;
-
private Activity mActivity;
@Mock
private Resources mActivityResources;
@@ -420,6 +418,25 @@
}
@Test
+ public void testResolveStartActivityIntent_shouldLaunchInFullscreen() {
+ final Intent intent = new Intent().setComponent(
+ new ComponentName(ApplicationProvider.getApplicationContext(),
+ MinimumDimensionActivity.class));
+ setupSplitRule(mActivity, intent);
+ final Activity primaryActivity = createMockActivity();
+ addSplitTaskFragments(primaryActivity, mActivity);
+
+ final TaskFragmentContainer container = mSplitController.resolveStartActivityIntent(
+ mTransaction, TASK_ID, intent, null /* launchingActivity */);
+ final TaskFragmentContainer primaryContainer = mSplitController.getContainerWithActivity(
+ mActivity);
+
+ assertNotNull(mSplitController.getActiveSplitForContainers(primaryContainer, container));
+ assertTrue(primaryContainer.areLastRequestedBoundsEqual(null));
+ assertTrue(container.areLastRequestedBoundsEqual(null));
+ }
+
+ @Test
public void testPlaceActivityInTopContainer() {
mSplitController.placeActivityInTopContainer(mActivity);
@@ -767,6 +784,48 @@
}
@Test
+ public void testResolveActivityToContainer_primaryActivityMinDimensionsNotSatisfied() {
+ final Activity activityBelow = createMockActivity();
+ setupSplitRule(mActivity, activityBelow);
+
+ doReturn(createActivityInfoWithMinDimensions()).when(mActivity).getActivityInfo();
+
+ final TaskFragmentContainer container = mSplitController.newContainer(activityBelow,
+ TASK_ID);
+ container.addPendingAppearedActivity(mActivity);
+
+ // Allow to split as primary.
+ boolean result = mSplitController.resolveActivityToContainer(mActivity,
+ true /* isOnReparent */);
+
+ assertTrue(result);
+ assertSplitPair(mActivity, activityBelow, true /* matchParentBounds */);
+ }
+
+ @Test
+ public void testResolveActivityToContainer_secondaryActivityMinDimensionsNotSatisfied() {
+ final Activity activityBelow = createMockActivity();
+ setupSplitRule(activityBelow, mActivity);
+
+ ActivityInfo aInfo = new ActivityInfo();
+ final Rect secondaryBounds = getSplitBounds(false /* isPrimary */);
+ aInfo.windowLayout = new ActivityInfo.WindowLayout(0, 0, 0, 0, 0,
+ secondaryBounds.width() + 1, secondaryBounds.height() + 1);
+ doReturn(aInfo).when(mActivity).getActivityInfo();
+
+ final TaskFragmentContainer container = mSplitController.newContainer(activityBelow,
+ TASK_ID);
+ container.addPendingAppearedActivity(mActivity);
+
+ // Allow to split as primary.
+ boolean result = mSplitController.resolveActivityToContainer(mActivity,
+ false /* isOnReparent */);
+
+ assertTrue(result);
+ assertSplitPair(activityBelow, mActivity, true /* matchParentBounds */);
+ }
+
+ @Test
public void testResolveActivityToContainer_inUnknownTaskFragment() {
doReturn(new Binder()).when(mSplitController).getInitialTaskFragmentToken(mActivity);
@@ -835,23 +894,10 @@
doReturn(activityToken).when(activity).getActivityToken();
doReturn(activity).when(mSplitController).getActivity(activityToken);
doReturn(TASK_ID).when(activity).getTaskId();
+ doReturn(new ActivityInfo()).when(activity).getActivityInfo();
return activity;
}
- /** Creates a mock TaskFragmentInfo for the given TaskFragment. */
- private TaskFragmentInfo createMockTaskFragmentInfo(@NonNull TaskFragmentContainer container,
- @NonNull Activity activity) {
- return new TaskFragmentInfo(container.getTaskFragmentToken(),
- mock(WindowContainerToken.class),
- new Configuration(),
- 1,
- true /* isVisible */,
- Collections.singletonList(activity.getActivityToken()),
- new Point(),
- false /* isTaskClearedForReuse */,
- false /* isTaskFragmentClearedForPip */);
- }
-
/** Creates a mock TaskFragment that has been registered and appeared in the organizer. */
private TaskFragmentContainer createMockTaskFragmentContainer(@NonNull Activity activity) {
final TaskFragmentContainer container = mSplitController.newContainer(activity, TASK_ID);
@@ -902,49 +948,10 @@
/** Setups a rule to always split the given activities. */
private void setupSplitRule(@NonNull Activity primaryActivity,
@NonNull Activity secondaryActivity) {
- final SplitRule splitRule = createSplitRule(primaryActivity, secondaryActivity,
- DEFAULT_FINISH_PRIMARY_WITH_SECONDARY, DEFAULT_FINISH_SECONDARY_WITH_PRIMARY,
- true /* clearTop */);
+ final SplitRule splitRule = createSplitRule(primaryActivity, secondaryActivity);
mSplitController.setEmbeddingRules(Collections.singleton(splitRule));
}
- /** Creates a rule to always split the given activity and the given intent. */
- private SplitRule createSplitRule(@NonNull Activity primaryActivity,
- @NonNull Intent secondaryIntent) {
- final Pair<Activity, Intent> targetPair = new Pair<>(primaryActivity, secondaryIntent);
- return new SplitPairRule.Builder(
- activityPair -> false,
- targetPair::equals,
- w -> true)
- .setSplitRatio(SPLIT_RATIO)
- .setShouldClearTop(true)
- .build();
- }
-
- /** Creates a rule to always split the given activities. */
- private SplitRule createSplitRule(@NonNull Activity primaryActivity,
- @NonNull Activity secondaryActivity) {
- return createSplitRule(primaryActivity, secondaryActivity,
- DEFAULT_FINISH_PRIMARY_WITH_SECONDARY, DEFAULT_FINISH_SECONDARY_WITH_PRIMARY,
- true /* clearTop */);
- }
-
- /** Creates a rule to always split the given activities with the given finish behaviors. */
- private SplitRule createSplitRule(@NonNull Activity primaryActivity,
- @NonNull Activity secondaryActivity, int finishPrimaryWithSecondary,
- int finishSecondaryWithPrimary, boolean clearTop) {
- final Pair<Activity, Activity> targetPair = new Pair<>(primaryActivity, secondaryActivity);
- return new SplitPairRule.Builder(
- targetPair::equals,
- activityIntentPair -> false,
- w -> true)
- .setSplitRatio(SPLIT_RATIO)
- .setFinishPrimaryWithSecondary(finishPrimaryWithSecondary)
- .setFinishSecondaryWithPrimary(finishSecondaryWithPrimary)
- .setShouldClearTop(clearTop)
- .build();
- }
-
/** Adds a pair of TaskFragments as split for the given activities. */
private void addSplitTaskFragments(@NonNull Activity primaryActivity,
@NonNull Activity secondaryActivity) {
@@ -973,39 +980,42 @@
secondaryContainer.setLastRequestedBounds(getSplitBounds(false /* isPrimary */));
}
- /** Gets the bounds of a TaskFragment that is in split. */
- private Rect getSplitBounds(boolean isPrimary) {
- final int width = (int) (TASK_BOUNDS.width() * SPLIT_RATIO);
- return isPrimary
- ? new Rect(TASK_BOUNDS.left, TASK_BOUNDS.top, TASK_BOUNDS.left + width,
- TASK_BOUNDS.bottom)
- : new Rect(TASK_BOUNDS.left + width, TASK_BOUNDS.top, TASK_BOUNDS.right,
- TASK_BOUNDS.bottom);
+ /** Asserts that the two given activities are in split. */
+ private void assertSplitPair(@NonNull Activity primaryActivity,
+ @NonNull Activity secondaryActivity) {
+ assertSplitPair(primaryActivity, secondaryActivity, false /* matchParentBounds */);
}
/** Asserts that the two given activities are in split. */
private void assertSplitPair(@NonNull Activity primaryActivity,
- @NonNull Activity secondaryActivity) {
+ @NonNull Activity secondaryActivity, boolean matchParentBounds) {
assertSplitPair(mSplitController.getContainerWithActivity(primaryActivity),
- mSplitController.getContainerWithActivity(secondaryActivity));
+ mSplitController.getContainerWithActivity(secondaryActivity), matchParentBounds);
+ }
+
+ private void assertSplitPair(@NonNull TaskFragmentContainer primaryContainer,
+ @NonNull TaskFragmentContainer secondaryContainer) {
+ assertSplitPair(primaryContainer, secondaryContainer, false /* matchParentBounds*/);
}
/** Asserts that the two given TaskFragments are in split. */
private void assertSplitPair(@NonNull TaskFragmentContainer primaryContainer,
- @NonNull TaskFragmentContainer secondaryContainer) {
+ @NonNull TaskFragmentContainer secondaryContainer, boolean matchParentBounds) {
assertNotNull(primaryContainer);
assertNotNull(secondaryContainer);
assertNotNull(mSplitController.getActiveSplitForContainers(primaryContainer,
secondaryContainer));
if (primaryContainer.mInfo != null) {
- assertTrue(primaryContainer.areLastRequestedBoundsEqual(
- getSplitBounds(true /* isPrimary */)));
+ final Rect primaryBounds = matchParentBounds ? new Rect()
+ : getSplitBounds(true /* isPrimary */);
+ assertTrue(primaryContainer.areLastRequestedBoundsEqual(primaryBounds));
assertTrue(primaryContainer.isLastRequestedWindowingModeEqual(
WINDOWING_MODE_MULTI_WINDOW));
}
if (secondaryContainer.mInfo != null) {
- assertTrue(secondaryContainer.areLastRequestedBoundsEqual(
- getSplitBounds(false /* isPrimary */)));
+ final Rect secondaryBounds = matchParentBounds ? new Rect()
+ : getSplitBounds(false /* isPrimary */);
+ assertTrue(secondaryContainer.areLastRequestedBoundsEqual(secondaryBounds));
assertTrue(secondaryContainer.isLastRequestedWindowingModeEqual(
WINDOWING_MODE_MULTI_WINDOW));
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
index 906e990..029503c 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
@@ -18,25 +18,46 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_BOUNDS;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createActivityInfoWithMinDimensions;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitRule;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.getSplitBounds;
+import static androidx.window.extensions.embedding.SplitPresenter.POSITION_END;
+import static androidx.window.extensions.embedding.SplitPresenter.POSITION_FILL;
+import static androidx.window.extensions.embedding.SplitPresenter.POSITION_START;
+import static androidx.window.extensions.embedding.SplitPresenter.getBoundsForPosition;
+import static androidx.window.extensions.embedding.SplitPresenter.getMinDimensions;
+import static androidx.window.extensions.embedding.SplitPresenter.shouldShowSideBySide;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
+import android.util.Pair;
+import android.util.Size;
import android.window.TaskFragmentInfo;
import android.window.WindowContainerTransaction;
+import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -56,8 +77,6 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class SplitPresenterTest {
- private static final int TASK_ID = 10;
- private static final Rect TASK_BOUNDS = new Rect(0, 0, 600, 1200);
@Mock
private Activity mActivity;
@@ -77,11 +96,7 @@
mPresenter = mController.mPresenter;
spyOn(mController);
spyOn(mPresenter);
- final Configuration activityConfig = new Configuration();
- activityConfig.windowConfiguration.setBounds(TASK_BOUNDS);
- activityConfig.windowConfiguration.setMaxBounds(TASK_BOUNDS);
- doReturn(mActivityResources).when(mActivity).getResources();
- doReturn(activityConfig).when(mActivityResources).getConfiguration();
+ mActivity = createMockActivity();
}
@Test
@@ -129,4 +144,108 @@
verify(mTransaction, never()).setWindowingMode(any(), anyInt());
}
+
+ @Test
+ public void testGetMinDimensionsForIntent() {
+ final Intent intent = new Intent(ApplicationProvider.getApplicationContext(),
+ MinimumDimensionActivity.class);
+ assertEquals(new Size(600, 1200), getMinDimensions(intent));
+ }
+
+ @Test
+ public void testShouldShowSideBySide() {
+ Activity secondaryActivity = createMockActivity();
+ final SplitRule splitRule = createSplitRule(mActivity, secondaryActivity);
+
+ assertTrue(shouldShowSideBySide(TASK_BOUNDS, splitRule));
+
+ // Set minDimensions of primary container to larger than primary bounds.
+ final Rect primaryBounds = getSplitBounds(true /* isPrimary */);
+ Pair<Size, Size> minDimensionsPair = new Pair<>(
+ new Size(primaryBounds.width() + 1, primaryBounds.height() + 1), null);
+
+ assertFalse(shouldShowSideBySide(TASK_BOUNDS, splitRule, minDimensionsPair));
+ }
+
+ @Test
+ public void testGetBoundsForPosition() {
+ Activity secondaryActivity = createMockActivity();
+ final SplitRule splitRule = createSplitRule(mActivity, secondaryActivity);
+ final Rect primaryBounds = getSplitBounds(true /* isPrimary */);
+ final Rect secondaryBounds = getSplitBounds(false /* isPrimary */);
+
+ assertEquals("Primary bounds must be reported.",
+ primaryBounds,
+ getBoundsForPosition(POSITION_START, TASK_BOUNDS, splitRule,
+ mActivity, null /* miniDimensionsPair */));
+
+ assertEquals("Secondary bounds must be reported.",
+ secondaryBounds,
+ getBoundsForPosition(POSITION_END, TASK_BOUNDS, splitRule,
+ mActivity, null /* miniDimensionsPair */));
+ assertEquals("Task bounds must be reported.",
+ new Rect(),
+ getBoundsForPosition(POSITION_FILL, TASK_BOUNDS, splitRule,
+ mActivity, null /* miniDimensionsPair */));
+
+ Pair<Size, Size> minDimensionsPair = new Pair<>(
+ new Size(primaryBounds.width() + 1, primaryBounds.height() + 1), null);
+
+ assertEquals("Fullscreen bounds must be reported because of min dimensions.",
+ new Rect(),
+ getBoundsForPosition(POSITION_START, TASK_BOUNDS,
+ splitRule, mActivity, minDimensionsPair));
+ }
+
+ @Test
+ public void testExpandSplitContainerIfNeeded() {
+ SplitContainer splitContainer = mock(SplitContainer.class);
+ Activity secondaryActivity = createMockActivity();
+ SplitRule splitRule = createSplitRule(mActivity, secondaryActivity);
+ TaskFragmentContainer primaryTf = mController.newContainer(mActivity, TASK_ID);
+ TaskFragmentContainer secondaryTf = mController.newContainer(secondaryActivity, TASK_ID);
+ doReturn(splitRule).when(splitContainer).getSplitRule();
+ doReturn(primaryTf).when(splitContainer).getPrimaryContainer();
+ doReturn(secondaryTf).when(splitContainer).getSecondaryContainer();
+
+ assertThrows(IllegalArgumentException.class, () ->
+ mPresenter.expandSplitContainerIfNeeded(mTransaction, splitContainer, mActivity,
+ null /* secondaryActivity */, null /* secondaryIntent */));
+
+ mPresenter.expandSplitContainerIfNeeded(mTransaction, splitContainer, mActivity,
+ secondaryActivity, null /* secondaryIntent */);
+
+ verify(mPresenter, never()).expandTaskFragment(any(), any());
+
+ doReturn(createActivityInfoWithMinDimensions()).when(secondaryActivity).getActivityInfo();
+
+ mPresenter.expandSplitContainerIfNeeded(mTransaction, splitContainer, mActivity,
+ secondaryActivity, null /* secondaryIntent */);
+
+ verify(mPresenter).expandTaskFragment(eq(mTransaction),
+ eq(primaryTf.getTaskFragmentToken()));
+ verify(mPresenter).expandTaskFragment(eq(mTransaction),
+ eq(secondaryTf.getTaskFragmentToken()));
+
+ clearInvocations(mPresenter);
+ mPresenter.expandSplitContainerIfNeeded(mTransaction, splitContainer, mActivity,
+ null /* secondaryActivity */, new Intent(ApplicationProvider
+ .getApplicationContext(), MinimumDimensionActivity.class));
+
+ verify(mPresenter).expandTaskFragment(eq(mTransaction),
+ eq(primaryTf.getTaskFragmentToken()));
+ verify(mPresenter).expandTaskFragment(eq(mTransaction),
+ eq(secondaryTf.getTaskFragmentToken()));
+ }
+
+ private Activity createMockActivity() {
+ final Activity activity = mock(Activity.class);
+ final Configuration activityConfig = new Configuration();
+ activityConfig.windowConfiguration.setBounds(TASK_BOUNDS);
+ activityConfig.windowConfiguration.setMaxBounds(TASK_BOUNDS);
+ doReturn(mActivityResources).when(activity).getResources();
+ doReturn(activityConfig).when(mActivityResources).getConfiguration();
+ doReturn(new ActivityInfo()).when(activity).getActivityInfo();
+ return activity;
+ }
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
index ebe202d..dd67e48 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
@@ -22,6 +22,9 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_BOUNDS;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
@@ -53,9 +56,6 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class TaskContainerTest {
- private static final int TASK_ID = 10;
- private static final Rect TASK_BOUNDS = new Rect(0, 0, 600, 1200);
-
@Mock
private SplitController mController;
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java
index af3ad70..d31342b 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java
@@ -16,6 +16,8 @@
package androidx.window.extensions.embedding;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -43,8 +45,6 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class TaskFragmentAnimationControllerTest {
- private static final int TASK_ID = 10;
-
@Mock
private TaskFragmentOrganizer mOrganizer;
private TaskFragmentAnimationController mAnimationController;
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
index fcbd8a3..28c2773 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
@@ -16,6 +16,9 @@
package androidx.window.extensions.embedding;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createMockTaskFragmentInfo;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static org.junit.Assert.assertEquals;
@@ -30,17 +33,13 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
-import android.annotation.NonNull;
import android.app.Activity;
import android.content.Intent;
-import android.content.res.Configuration;
-import android.graphics.Point;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.window.TaskFragmentInfo;
-import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -55,7 +54,6 @@
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
/**
@@ -68,8 +66,6 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class TaskFragmentContainerTest {
- private static final int TASK_ID = 10;
-
@Mock
private SplitPresenter mPresenter;
@Mock
@@ -311,18 +307,4 @@
doReturn(activity).when(mController).getActivity(activityToken);
return activity;
}
-
- /** Creates a mock TaskFragmentInfo for the given TaskFragment. */
- private TaskFragmentInfo createMockTaskFragmentInfo(@NonNull TaskFragmentContainer container,
- @NonNull Activity activity) {
- return new TaskFragmentInfo(container.getTaskFragmentToken(),
- mock(WindowContainerToken.class),
- new Configuration(),
- 1,
- true /* isVisible */,
- Collections.singletonList(activity.getActivityToken()),
- new Point(),
- false /* isTaskClearedForReuse */,
- false /* isTaskFragmentClearedForPip */);
- }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 0e8dc63..0a33414 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -2220,11 +2220,10 @@
private void animateSwitchBubbles() {
// If we're no longer expanded, this is meaningless.
if (!mIsExpanded) {
+ mIsBubbleSwitchAnimating = false;
return;
}
- mIsBubbleSwitchAnimating = true;
-
// The surface contains a screenshot of the animating out bubble, so we just need to animate
// it out (and then release the GraphicBuffer).
PhysicsAnimator.getInstance(mAnimatingOutSurfaceContainer).cancel();
@@ -2838,6 +2837,7 @@
}, 0);
if (!mIsExpansionAnimating) {
+ mIsBubbleSwitchAnimating = true;
mSurfaceSynchronizer.syncSurfaceAndRun(() -> {
post(this::animateSwitchBubbles);
});
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java
index b9ddd36..0f9260c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java
@@ -54,7 +54,13 @@
default void onTaskDescriptionChanged(RunningTaskInfo taskInfo) { }
- default void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { }
+ /**
+ * @return whether the snapshot is consumed and the lifecycle of the snapshot extends beyond
+ * the lifecycle of this callback.
+ */
+ default boolean onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) {
+ return false;
+ }
default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
index 85e2654..9e0a48b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
@@ -275,9 +275,15 @@
}
case ON_TASK_SNAPSHOT_CHANGED: {
Trace.beginSection("onTaskSnapshotChanged");
+ final TaskSnapshot snapshot = (TaskSnapshot) msg.obj;
+ boolean snapshotConsumed = false;
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1,
- (TaskSnapshot) msg.obj);
+ boolean consumed = mTaskStackListeners.get(i).onTaskSnapshotChanged(
+ msg.arg1, snapshot);
+ snapshotConsumed |= consumed;
+ }
+ if (!snapshotConsumed && snapshot.getHardwareBuffer() != null) {
+ snapshot.getHardwareBuffer().close();
}
Trace.endSection();
break;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 7ea32a6..41e2364 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -76,6 +76,7 @@
import android.os.RemoteException;
import android.util.Log;
import android.util.Slog;
+import android.view.Choreographer;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner;
import android.view.RemoteAnimationAdapter;
@@ -1124,6 +1125,7 @@
mDividerFadeInAnimator.cancel();
return;
}
+ transaction.setFrameTimelineVsync(Choreographer.getInstance().getVsyncId());
transaction.setAlpha(dividerLeash, (float) animation.getAnimatedValue());
transaction.apply();
});
@@ -1216,17 +1218,23 @@
@Override
public void onLayoutPositionChanging(SplitLayout layout) {
- mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t, false /* applyResizingOffset */));
+ final SurfaceControl.Transaction t = mTransactionPool.acquire();
+ t.setFrameTimelineVsync(Choreographer.getInstance().getVsyncId());
+ updateSurfaceBounds(layout, t, false /* applyResizingOffset */);
+ t.apply();
+ mTransactionPool.release(t);
}
@Override
public void onLayoutSizeChanging(SplitLayout layout) {
- mSyncQueue.runInSync(t -> {
- setResizingSplits(true /* resizing */);
- updateSurfaceBounds(layout, t, true /* applyResizingOffset */);
- mMainStage.onResizing(getMainStageBounds(), t);
- mSideStage.onResizing(getSideStageBounds(), t);
- });
+ final SurfaceControl.Transaction t = mTransactionPool.acquire();
+ t.setFrameTimelineVsync(Choreographer.getInstance().getVsyncId());
+ setResizingSplits(true /* resizing */);
+ updateSurfaceBounds(layout, t, true /* applyResizingOffset */);
+ mMainStage.onResizing(getMainStageBounds(), t);
+ mSideStage.onResizing(getSideStageBounds(), t);
+ t.apply();
+ mTransactionPool.release(t);
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index cde4247..95bc579 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -389,6 +389,9 @@
reportDrawn();
// In case window manager leaks us, make sure we don't retain the snapshot.
+ if (mSnapshot.getHardwareBuffer() != null) {
+ mSnapshot.getHardwareBuffer().close();
+ }
mSnapshot = null;
mSurfaceControl.release();
}
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index ccc23b7..8756f1e 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -2320,6 +2320,10 @@
*/
public final void start() {
native_start();
+ synchronized(mBufferLock) {
+ cacheBuffers(true /* input */);
+ cacheBuffers(false /* input */);
+ }
}
private native final void native_start();
@@ -3951,9 +3955,6 @@
+ "objects and attach to QueueRequest objects.");
}
if (mCachedInputBuffers == null) {
- cacheBuffers(true /* input */);
- }
- if (mCachedInputBuffers == null) {
throw new IllegalStateException();
}
// FIXME: check codec status
@@ -3992,9 +3993,6 @@
+ "Please use getOutputFrame to get output frames.");
}
if (mCachedOutputBuffers == null) {
- cacheBuffers(false /* input */);
- }
- if (mCachedOutputBuffers == null) {
throw new IllegalStateException();
}
// FIXME: check codec status
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
index 9a64b58..ed70ab9 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
@@ -1653,7 +1653,7 @@
modeList.contains(CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF));
checkArrayValuesInRange(key, modes,
CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF,
- CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_ON);
+ CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION);
return modes;
}
diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml
index e2fa97f..beabaf1 100644
--- a/packages/CompanionDeviceManager/res/values-fa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml
@@ -39,7 +39,7 @@
<string name="profile_name_generic" msgid="6851028682723034988">"دستگاه"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
<string name="consent_yes" msgid="8344487259618762872">"اجازه دادن"</string>
- <string name="consent_no" msgid="2640796915611404382">"مجاز نبودن"</string>
+ <string name="consent_no" msgid="2640796915611404382">"اجازه ندادن"</string>
<string name="consent_back" msgid="2560683030046918882">"برگشت"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"انتقال اجازههای برنامه به ساعت"</string>
<string name="permission_sync_summary" msgid="8873391306499120778">"برای آسانتر کردن راهاندازی ساعت، برنامههای نصبشده در ساعت درحین راهاندازی از همان اجازههای تلفن استفاده خواهند کرد.\n\n ممکن است این اجازهها شامل دسترسی به میکروفون و مکان ساعت باشد."</string>
diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml
index b23ac10..1ac3999 100644
--- a/packages/CompanionDeviceManager/res/values-hi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml
@@ -19,7 +19,7 @@
<string name="app_label" msgid="4470785958457506021">"सहयोगी डिवाइस मैनेजर"</string>
<string name="confirmation_title" msgid="3785000297483688997">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ऐक्सेस करने की अनुमति दें"</string>
<string name="profile_name_watch" msgid="576290739483672360">"स्मार्टवॉच"</string>
- <string name="chooser_title" msgid="2262294130493605839">"कोई <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चुनें, ताकि उसे <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> की मदद से प्रबंधित किया जा सके"</string>
+ <string name="chooser_title" msgid="2262294130493605839">"कोई <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चुनें, ताकि उसे <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> की मदद से मैनेज किया जा सके"</string>
<string name="summary_watch" msgid="3002344206574997652">"यह ऐप्लिकेशन, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को मैनेज करने के लिए ज़रूरी है. <xliff:g id="APP_NAME">%2$s</xliff:g> आपकी सूचनाओं पर कार्रवाई कर पाएगा. साथ ही, इसे आपके फ़ोन, एसएमएस, संपर्कों, कैलेंडर, कॉल लॉग, और आस-पास मौजूद डिवाइसों को ऐक्सेस करने की अनुमति मिल पाएगी."</string>
<string name="permission_apps" msgid="6142133265286656158">"ऐप्लिकेशन"</string>
<string name="permission_apps_summary" msgid="798718816711515431">"अपने फ़ोन के ऐप्लिकेशन को स्ट्रीम करें"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml
index 3a345fb..d641f29 100644
--- a/packages/CompanionDeviceManager/res/values-ky/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml
@@ -38,7 +38,7 @@
<string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> түзмөгүңүздүн атынан түзмөктөрүңүздүн ортосунда колдонмолорду тышкы экранга чыгарууга уруксат сурап жатат"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"түзмөк"</string>
<string name="summary_generic" msgid="2346762210105903720"></string>
- <string name="consent_yes" msgid="8344487259618762872">"Уруксат берүү"</string>
+ <string name="consent_yes" msgid="8344487259618762872">"Ооба"</string>
<string name="consent_no" msgid="2640796915611404382">"Уруксат берилбесин"</string>
<string name="consent_back" msgid="2560683030046918882">"Артка"</string>
<string name="permission_sync_confirmation_title" msgid="667074294393493186">"Колдонмонун уруксаттарын саатка өткөрүү"</string>
diff --git a/packages/PackageInstaller/res/values-it/strings.xml b/packages/PackageInstaller/res/values-it/strings.xml
index 979de60..74f7d908 100644
--- a/packages/PackageInstaller/res/values-it/strings.xml
+++ b/packages/PackageInstaller/res/values-it/strings.xml
@@ -46,7 +46,7 @@
<string name="out_of_space_dlg_text" msgid="8727714096031856231">"Impossibile installare <xliff:g id="APP_NAME">%1$s</xliff:g>. Libera dello spazio e riprova."</string>
<string name="app_not_found_dlg_title" msgid="5107924008597470285">"App non trovata"</string>
<string name="app_not_found_dlg_text" msgid="5219983779377811611">"Impossibile trovare l\'applicazione nell\'elenco di applicazioni installate."</string>
- <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"Autorizzazione non concessa"</string>
+ <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"Non autorizzate"</string>
<string name="user_is_not_allowed_dlg_text" msgid="3468447791330611681">"L\'utente corrente non è autorizzato a eseguire questa disinstallazione."</string>
<string name="generic_error_dlg_title" msgid="5863195085927067752">"Errore"</string>
<string name="generic_error_dlg_text" msgid="5287861443265795232">"Impossibile disinstallare l\'app."</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 04549b2..b1aeebe 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -124,7 +124,7 @@
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"دسترسی سیمکارت"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"صدای HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"صدای HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"سمعکها"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"سمعک"</string>
<string name="bluetooth_profile_le_audio" msgid="5158149987518342036">"LE_AUDIO"</string>
<string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"به سمعک متصل شد"</string>
<string name="bluetooth_le_audio_profile_summary_connected" msgid="3162538609379333442">"متصل به LE_AUDIO"</string>
@@ -144,7 +144,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"استفاده برای تلفن صوتی"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"استفاده برای انتقال فایل"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"استفاده برای چاپ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"استفاده برای سمعکها"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"استفاده کردن برای سمعک"</string>
<string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"استفاده برای LE_AUDIO"</string>
<string name="bluetooth_pairing_accept" msgid="2054232610815498004">"مرتبطسازی"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"مرتبطسازی"</string>
@@ -184,7 +184,7 @@
<string name="launch_defaults_some" msgid="3631650616557252926">"بعضی پیشفرضها تنظیم شدهاند"</string>
<string name="launch_defaults_none" msgid="8049374306261262709">"پیشفرضی تنظیم نشده است"</string>
<string name="tts_settings" msgid="8130616705989351312">"تنظیمات متن به گفتار"</string>
- <string name="tts_settings_title" msgid="7602210956640483039">"خروجی تبدیل متن به گفتار"</string>
+ <string name="tts_settings_title" msgid="7602210956640483039">"خروجی نوشتار به گفتار"</string>
<string name="tts_default_rate_title" msgid="3964187817364304022">"سرعت گفتار"</string>
<string name="tts_default_rate_summary" msgid="3781937042151716987">"سرعتی که متن خوانده میشود"</string>
<string name="tts_default_pitch_title" msgid="6988592215554485479">"زیر و بمی صدا"</string>
@@ -643,7 +643,7 @@
<string name="dream_complication_title_date" msgid="8661176085446135789">"تاریخ"</string>
<string name="dream_complication_title_weather" msgid="598609151677172783">"آبوهوا"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"کیفیت هوا"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"اطلاعات ارسال محتوا"</string>
+ <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"اطلاعات پخش محتوا"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"انتخاب عکس نمایه"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"نماد کاربر پیشفرض"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"صفحهکلید فیزیکی"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 8c3f1fa..861c183 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -371,7 +371,7 @@
<string name="show_hw_layers_updates" msgid="5268370750002509767">"Atualizações de camadas de hardware"</string>
<string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"Piscar camadas de hardware em verde ao atualizar"</string>
<string name="debug_hw_overdraw" msgid="8944851091008756796">"Depurar overdraw da GPU"</string>
- <string name="disable_overlays" msgid="4206590799671557143">"Desativar sobreposição HW"</string>
+ <string name="disable_overlays" msgid="4206590799671557143">"Desativar sobreposição de HW"</string>
<string name="disable_overlays_summary" msgid="1954852414363338166">"Sempre usar a GPU para composição de tela"</string>
<string name="simulate_color_space" msgid="1206503300335835151">"Simular espaço de cores"</string>
<string name="enable_opengl_traces_title" msgid="4638773318659125196">"Ativar rastream. OpenGL"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 8c3f1fa..861c183 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -371,7 +371,7 @@
<string name="show_hw_layers_updates" msgid="5268370750002509767">"Atualizações de camadas de hardware"</string>
<string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"Piscar camadas de hardware em verde ao atualizar"</string>
<string name="debug_hw_overdraw" msgid="8944851091008756796">"Depurar overdraw da GPU"</string>
- <string name="disable_overlays" msgid="4206590799671557143">"Desativar sobreposição HW"</string>
+ <string name="disable_overlays" msgid="4206590799671557143">"Desativar sobreposição de HW"</string>
<string name="disable_overlays_summary" msgid="1954852414363338166">"Sempre usar a GPU para composição de tela"</string>
<string name="simulate_color_space" msgid="1206503300335835151">"Simular espaço de cores"</string>
<string name="enable_opengl_traces_title" msgid="4638773318659125196">"Ativar rastream. OpenGL"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
index 1804e86..c829bc3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
@@ -33,6 +33,7 @@
import static com.android.settingslib.media.LocalMediaManager.MediaDeviceState.STATE_SELECTED;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.media.MediaRoute2Info;
@@ -268,6 +269,20 @@
}
/**
+ * Checks if route's volume is fixed, if true, we should disable volume control for the device.
+ *
+ * @return route for this device is fixed.
+ */
+ @SuppressLint("NewApi")
+ public boolean isVolumeFixed() {
+ if (mRouteInfo == null) {
+ Log.w(TAG, "RouteInfo is empty, regarded as volume fixed.");
+ return true;
+ }
+ return mRouteInfo.getVolumeHandling() == MediaRoute2Info.PLAYBACK_VOLUME_FIXED;
+ }
+
+ /**
* Transfer MediaDevice for media
*
* @return result of transfer media
@@ -439,7 +454,7 @@
* Check if it is muting expected device
* @return {@code true} if it is muting expected device, otherwise return {@code false}
*/
- protected boolean isMutingExpectedDevice() {
+ public boolean isMutingExpectedDevice() {
return false;
}
diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING
index b01fd6d..3bd6d51 100644
--- a/packages/SystemUI/TEST_MAPPING
+++ b/packages/SystemUI/TEST_MAPPING
@@ -20,6 +20,25 @@
]
}
],
+ "presubmit-sysui": [
+ {
+ "name": "PlatformScenarioTests",
+ "options": [
+ {
+ "include-filter": "android.platform.test.scenario.sysui"
+ },
+ {
+ "include-annotation": "android.platform.test.scenario.annotation.Scenario"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.Postsubmit"
+ }
+ ]
+ }
+ ],
"presubmit": [
{
"name": "SystemUIGoogleTests",
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
index 8e34c47..b3dd955 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
@@ -435,7 +435,7 @@
val h = "H${hct.hue.roundToInt().toString().padEnd(width)}"
val c = "C${hct.chroma.roundToInt().toString().padEnd(width)}"
val t = "T${CamUtils.lstarFromInt(color).roundToInt().toString().padEnd(width)}"
- val hex = Integer.toHexString(color).replaceRange(0, 2, "").uppercase()
+ val hex = Integer.toHexString(color and 0xffffff).padStart(6, '0').uppercase()
return "$h$c$t = #$hex"
}
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index e48e4559..32848fd 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Teks is gekopieer"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Prent is gekopieer"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Inhoud is gekopieer"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Knipbordredigeerder"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Knipbord"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Prentvoorskou"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"wysig"</string>
<string name="add" msgid="81036585205287996">"Voeg by"</string>
<string name="manage_users" msgid="1823875311934643849">"Bestuur gebruikers"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Sleep na verdeelde skerm word nie vir hierdie kennisgewing gesteun nie."</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 1991259..f2d56b2 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"ካሜራ"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ስልክ"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"የድምጽ እርዳታ"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"የኪስ ቦርሳ"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"የQR ኮድ መቃኛ"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"ክፈት"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"መሣሪያ ተቆልፏል"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"ጽሁፍ ተቀድቷል"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"ምስል ተቀድቷል"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"ይዘት ተቀድቷል"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"የቅንጥብ ሰሌዳ አርታዒ"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"የቅንጥብ ሰሌዳ"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"የምስል ቅድመ-እይታ"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"አርትዕ"</string>
<string name="add" msgid="81036585205287996">"አክል"</string>
<string name="manage_users" msgid="1823875311934643849">"ተጠቃሚዎችን ያስተዳድሩ"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ይህ ማሳወቂያ ወደ Splitscreen መጎተትን አይደግፍም።"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 9bb455e..ad1a34d 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -973,14 +973,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"تم نسخ النص."</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"تم نسخ الصورة."</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"تم نسخ المحتوى."</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"محرِّر الحافظة"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"الحافظة"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"معاينة الصورة"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"التعديل"</string>
<string name="add" msgid="81036585205287996">"إضافة"</string>
<string name="manage_users" msgid="1823875311934643849">"إدارة المستخدمين"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"لا يتيح هذا الإشعار السحب لتقسيم الشاشة."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 8286ee6..173a33e 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"পাঠ প্ৰতিলিপি কৰা হ’ল"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"প্ৰতিচ্ছবি প্ৰতিলিপি কৰা হ’ল"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"সমল প্ৰতিলিপি কৰা হ’ল"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"ক্লিপব’ৰ্ড সম্পাদক"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"ক্লিপব’ৰ্ড"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"প্ৰতিচ্ছবিৰ পূৰ্বদৰ্শন"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"সম্পাদনা কৰক"</string>
<string name="add" msgid="81036585205287996">"যোগ দিয়ক"</string>
<string name="manage_users" msgid="1823875311934643849">"ব্যৱহাৰকাৰী পৰিচালনা কৰক"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"এই জাননীটোৱে টানি আনি এৰাৰ পৰা বিভাজিত স্ক্ৰীন সমৰ্থন নকৰে।"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 1620056..f1a3c69 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Mətn kopyalanıb"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Şəkil Kopyalanıb"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Məzmun kopyalanıb"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Mübadilə Buferi Redaktoru"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Mübadilə buferi"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Şəkil önizləməsi"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"redaktə"</string>
<string name="add" msgid="81036585205287996">"Əlavə edin"</string>
<string name="manage_users" msgid="1823875311934643849">"İstifadəçiləri idarə edin"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Bu bildiriş Ayrılmış ekrana sürüşdürməyi dəstəkləmir."</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index e18316f..615a709 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -952,14 +952,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Tekst je kopiran"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Slika je kopirana"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Sadržaj je kopiran"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Uređivač privremene memorije"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Privremena memorija"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Pregled slike"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"izmenite"</string>
<string name="add" msgid="81036585205287996">"Dodaj"</string>
<string name="manage_users" msgid="1823875311934643849">"Upravljajte korisnicima"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Ovo obaveštenje ne podržava prevlačenje na podeljeni ekran."</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 5ea3a8c..6301028 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -959,14 +959,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Тэкст скапіраваны"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Відарыс скапіраваны"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Змесціва скапіравана"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Рэдактар буфера абмену"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Буфер абмену"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Папярэдні прагляд відарыса"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"змяніць"</string>
<string name="add" msgid="81036585205287996">"Дадаць"</string>
<string name="manage_users" msgid="1823875311934643849">"Кіраванне карыстальнікамі"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Гэта апавяшчэнне нельга перацягнуць на падзелены экран."</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index add650d..6e1b68c 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Текстът е копиран"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Изображението е копирано"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Съдържанието е копирано"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Редактор на буферната памет"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Буферна памет"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Визуализация на изображението"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"редактиране"</string>
<string name="add" msgid="81036585205287996">"Добавяне"</string>
<string name="manage_users" msgid="1823875311934643849">"Управление на потребителите"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Това известие не поддържа плъзгане за разделяне на екрана."</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index a9e95f1..f4f897e 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"ক্যামেরা"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ফোন"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ভয়েস সহায়তা"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"ওয়ালেট"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR কোড স্ক্যানার"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"আনলক করুন"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"ডিভাইস লক করা আছে"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"টেক্সট কপি করা হয়েছে"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"ছবি কপি করা হয়েছে"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"কন্টেন্ট কপি করা হয়েছে"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"ক্লিপবোর্ড এডিটর"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"ক্লিপবোর্ড"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"ছবির প্রিভিউ"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"এডিট করতে"</string>
<string name="add" msgid="81036585205287996">"যোগ করুন"</string>
<string name="manage_users" msgid="1823875311934643849">"ব্যবহারকারীদের ম্যানেজ করুন"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"স্প্লিটস্ক্রিন মোডে এই বিজ্ঞপ্তি টেনে আনা যাবে না।"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index e814a5c..e8857ad 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"El text s\'ha copiat"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"La imatge s\'ha copiat"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"El contingut s\'ha copiat"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor del porta-retalls"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Porta-retalls"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Previsualització de la imatge"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"editar"</string>
<string name="add" msgid="81036585205287996">"Afegeix"</string>
<string name="manage_users" msgid="1823875311934643849">"Gestiona els usuaris"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Aquesta notificació no es pot arrossegar a la pantalla dividida."</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 69de3b5..f46f82a 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -959,14 +959,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Text byl zkopírován"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Obrázek byl zkopírován"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Obsah byl zkopírován"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor schránky"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Schránka"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Náhled obrázku"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"upravit"</string>
<string name="add" msgid="81036585205287996">"Přidat"</string>
<string name="manage_users" msgid="1823875311934643849">"Správa uživatelů"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Toto oznámení nepodporuje přetažení na rozdělenou obrazovku."</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 8b2ef4e..dbbd74f 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -372,7 +372,7 @@
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Din organisation ejer denne enhed og overvåger muligvis netværkstrafikken"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ejer denne enhed og overvåger muligvis netværkstrafikken"</string>
<string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"Denne enhed er leveret af <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
- <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"Denne enhed tilhører din organisation, og den har forbindelse til nettet via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"Denne enhed tilhører din organisation, og den har forbindelse til internettet via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="quick_settings_disclosure_named_management_named_vpn" msgid="2169227918166358741">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, og den har forbindelse til nettet via <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
<string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Denne enhed tilhører din organisation"</string>
<string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
@@ -382,8 +382,8 @@
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> kan overvåge netværkstrafik på din arbejdsprofil"</string>
<string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"Din it-administrator kan se netværksaktivitet på din arbejdsprofil"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Netværket kan være overvåget"</string>
- <string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"Denne enhed har forbindelse til nettet via VPN-forbindelser"</string>
- <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"Dine arbejdsapps har forbindelse til nettet via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"Denne enhed har forbindelse til internettet via VPN-forbindelser"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"Dine arbejdsapps har forbindelse til internettet via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="451254750289172191">"Dine personlige apps har forbindelse til internettet via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="quick_settings_disclosure_named_vpn" msgid="6191822916936028208">"Denne enhed har forbindelse til internettet via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_financed_device" msgid="3659962357973919387">"Denne enhed er leveret af <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
@@ -401,9 +401,9 @@
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Der er installeret et nøglecenter på denne enhed. Din sikre netværkstrafik kan overvåges eller ændres."</string>
<string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Din administrator har aktiveret netværksregistrering, som overvåger trafik på din enhed."</string>
<string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Din administrator har aktiveret netværkslogging, som overvåger trafik på din arbejdsprofil, men ikke på din personlige profil."</string>
- <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Denne enhed har forbindelse til nettet via <xliff:g id="VPN_APP">%1$s</xliff:g>. Din netværksaktivitet, herunder mails og browserdata, er synlig for din it-administrator."</string>
- <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Denne enhed har forbindelse til nettet via <xliff:g id="VPN_APP_0">%1$s</xliff:g> og <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Din netværksaktivitet, herunder mails og browserdata, er synlig for din it-administrator."</string>
- <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Dine arbejdsapps har forbindelse til nettet via <xliff:g id="VPN_APP">%1$s</xliff:g>. Din netværksaktivitet i arbejdsapps, herunder mails og browserdata, er synlig for din it-administrator og VPN-udbyder."</string>
+ <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Denne enhed har forbindelse til internettet via <xliff:g id="VPN_APP">%1$s</xliff:g>. Din netværksaktivitet, herunder mails og browserdata, er synlig for din it-administrator."</string>
+ <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Denne enhed har forbindelse til internettet via <xliff:g id="VPN_APP_0">%1$s</xliff:g> og <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Din netværksaktivitet, herunder mails og browserdata, er synlig for din it-administrator."</string>
+ <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Dine arbejdsapps har forbindelse til internettet via <xliff:g id="VPN_APP">%1$s</xliff:g>. Din netværksaktivitet i arbejdsapps, herunder mails og browserdata, er synlig for din it-administrator og VPN-udbyder."</string>
<string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Dine personlige apps har forbindelse til nettet via <xliff:g id="VPN_APP">%1$s</xliff:g>. Din netværksaktivitet, herunder mails og browserdata, er synlig for din VPN-udbyder."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
<string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Åbn VPN-indstillinger"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Teksten blev kopieret"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Billedet blev kopieret"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Indholdet blev kopieret"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Redigeringsværktøj til udklipsholder"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Udklipsholder"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Forhåndsvisning af billede"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"redigere"</string>
<string name="add" msgid="81036585205287996">"Tilføj"</string>
<string name="manage_users" msgid="1823875311934643849">"Administrer brugere"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Denne notifikation kan ikke trækkes til en opdelt skærm."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 52b2209..f786625 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Text kopiert"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Bild kopiert"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Inhalt kopiert"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Zwischenablage bearbeiten"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Zwischenablage"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Bildvorschau"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"bearbeiten"</string>
<string name="add" msgid="81036585205287996">"Hinzufügen"</string>
<string name="manage_users" msgid="1823875311934643849">"Nutzer verwalten"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Diese Benachrichtigung lässt sich nicht auf einen geteilten Bildschirm ziehen."</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index e3b8581..83a1d18 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Cámara"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Teléfono"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistente voz"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Billetera"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Escáner de código QR"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"Ver en modo de demostración"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string>
- <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Billetera"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"Prepárate para realizar compras rápidas y seguras con tu teléfono"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Mostrar todo"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Presiona para abrir"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Se copió el texto"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Se copió la imagen"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Se copió el contenido"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor de portapapeles"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Portapapeles"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Vista previa de la imagen"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"editar"</string>
<string name="add" msgid="81036585205287996">"Agregar"</string>
<string name="manage_users" msgid="1823875311934643849">"Administrar usuarios"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Esta notificación no admite arrastrar entre pantallas divididas."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index f2f4bbb..9b79f71 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Cámara"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Teléfono"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistente voz"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"Cartera"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Escáner de códigos QR"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
@@ -403,7 +403,7 @@
<string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Tu administrador ha activado el registro de la red, por lo que se monitorizará el tráfico de tu perfil de trabajo, aunque no el de tu perfil personal."</string>
<string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Este dispositivo está conectado a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. Tu actividad de red, como los correos electrónicos y los datos de navegación, es visible para tu administrador de TI."</string>
<string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Este dispositivo está conectado a Internet a través de <xliff:g id="VPN_APP_0">%1$s</xliff:g> y <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Tu actividad de red, como los correos electrónicos y los datos de navegación, es visible para tu administrador de TI."</string>
- <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Tus aplicaciones de trabajo están conectadas a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. Tu actividad de red en estas aplicaciones, incluidos los correos electrónicos y los datos de navegación, es visible para tu administrador de TI y tu proveedor de VPN."</string>
+ <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Tus aplicaciones de trabajo están conectadas a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. Tu actividad de red en las aplicaciones de trabajo, incluidos los correos electrónicos y los datos de navegación, es visible para tu administrador de TI y tu proveedor de VPN."</string>
<string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Tus aplicaciones personales están conectadas a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. Tu actividad de red, como los correos electrónicos y los datos de navegación, es visible para tu proveedor de VPN."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
<string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Abrir ajustes de VPN"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Texto copiado"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Imagen copiada"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Contenido copiado"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor del portapapeles"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Portapapeles"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Vista previa de la imagen"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"editar"</string>
<string name="add" msgid="81036585205287996">"Añadir"</string>
<string name="manage_users" msgid="1823875311934643849">"Gestionar usuarios"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Esta notificación no se puede arrastrar a la pantalla dividida."</string>
diff --git a/packages/SystemUI/res/values-es/tiles_states_strings.xml b/packages/SystemUI/res/values-es/tiles_states_strings.xml
index e4310af..78c7669 100644
--- a/packages/SystemUI/res/values-es/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es/tiles_states_strings.xml
@@ -64,7 +64,7 @@
<string-array name="tile_states_rotation">
<item msgid="4578491772376121579">"No disponible"</item>
<item msgid="5776427577477729185">"Desactivada"</item>
- <item msgid="7105052717007227415">"Activada"</item>
+ <item msgid="7105052717007227415">"Activado"</item>
</string-array>
<string-array name="tile_states_bt">
<item msgid="5330252067413512277">"No disponible"</item>
@@ -89,7 +89,7 @@
<string-array name="tile_states_color_correction">
<item msgid="2840507878437297682">"No disponible"</item>
<item msgid="1909756493418256167">"Desactivada"</item>
- <item msgid="4531508423703413340">"Activada"</item>
+ <item msgid="4531508423703413340">"Activado"</item>
</string-array>
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"No disponible"</item>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 9bd5f0ad..46f9f51 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kaamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Häälabi"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"Rahakott"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR-koodi skanner"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Luku avamine"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Seade on lukustatud"</string>
@@ -372,7 +372,7 @@
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Teie organisatsioon on selle seadme omanik ja võib jälgida võrguliiklust"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> on selle seadme omanik ja võib jälgida võrguliiklust"</string>
<string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"Selle seadme on andnud <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
- <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"See seade kuulub teie organisatsioonile ja on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"See seade kuulub teie organisatsioonile ja on ühendatud internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu"</string>
<string name="quick_settings_disclosure_named_management_named_vpn" msgid="2169227918166358741">"See seade kuulub organisatsioonile <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ja on internetiga rakenduse <xliff:g id="VPN_APP">%2$s</xliff:g> kaudu ühendatud"</string>
<string name="quick_settings_disclosure_management" msgid="5515296598440684962">"See seade kuulub teie organisatsioonile"</string>
<string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Selle seadme omanik on <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
@@ -382,8 +382,8 @@
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> võib jälgida võrguliiklust teie tööprofiilil"</string>
<string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"Tööprofiili võrgutegevused on teie IT-administraatorile nähtavad"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Võrku võidakse jälgida"</string>
- <string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"See seade on internetiga VPN-ide kaudu ühendatud"</string>
- <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"Teie töörakendused on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud"</string>
+ <string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"See seade on ühendatud internetiga VPN-ide kaudu"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"Teie töörakendused on ühendatud internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu"</string>
<string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="451254750289172191">"Teie isiklikud rakendused on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud"</string>
<string name="quick_settings_disclosure_named_vpn" msgid="6191822916936028208">"See seade on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud"</string>
<string name="monitoring_title_financed_device" msgid="3659962357973919387">"Selle seadme on andnud <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
@@ -402,8 +402,8 @@
<string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Teie administraator lülitas sisse võrgu logimise funktsiooni, mis jälgib teie seadmes liiklust."</string>
<string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Teie administraator on sisse lülitanud võrgu logimise funktsiooni, mis jälgib liiklust teie võrguprofiilil, kuid mitte teie isiklikul profiilil."</string>
<string name="monitoring_description_named_vpn" msgid="7502657784155456414">"See seade on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud. Teie võrgutegevus, sealhulgas meilid ja sirvimisandmed, on nähtav teie IT-administraatorile."</string>
- <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"See seade on internetiga rakenduse <xliff:g id="VPN_APP_0">%1$s</xliff:g> ja <xliff:g id="VPN_APP_1">%2$s</xliff:g> kaudu ühendatud. Teie võrgutegevus, sealhulgas meilid ja sirvimisandmed, on nähtav teie IT-administraatorile."</string>
- <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Teie töörakendused on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud. Teie töörakenduste võrgutegevus, sealhulgas meilid ja sirvimisandmed, on nähtav teie IT-administraatorile ning VPN-i teenusepakkujale."</string>
+ <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"See seade on ühendatud internetiga rakenduste <xliff:g id="VPN_APP_0">%1$s</xliff:g> ja <xliff:g id="VPN_APP_1">%2$s</xliff:g> kaudu. Teie võrgutegevused (sealhulgas meilid ja sirvimisandmed) on nähtavad teie IT-administraatorile."</string>
+ <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Teie töörakendused on ühendatud internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu. Teie töörakenduste võrgutegevused (sealhulgas meilid ja sirvimisandmed) on nähtavad teie IT-administraatorile ning VPN-i teenusepakkujale."</string>
<string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Teie isiklikud rakendused on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud. Teie võrgutegevus, sealhulgas meilid ja sirvimisandmed, on nähtav teie VPN-i teenusepakkujale."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
<string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"VPN-i seadete avamine"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"Kuva demorežiim"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Äratus"</string>
- <string name="wallet_title" msgid="5369767670735827105">"Rahakott"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"Seadistage kiirem ja turvalisem viis telefoniga ostmiseks"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Kuva kõik"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Puudutage avamiseks"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Tekst kopeeriti"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Pilt kopeeriti"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Sisu kopeeriti"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Lõikelaua sisu muutmine"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Lõikelaud"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Pildi eelvaade"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"muutmine"</string>
<string name="add" msgid="81036585205287996">"Lisa"</string>
<string name="manage_users" msgid="1823875311934643849">"Kasutajate haldamine"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"See märguanne ei toeta jagatud ekraanikuvale lohistamist."</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 896f7a0..fc76097 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -406,7 +406,7 @@
<string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Laneko aplikazioak <xliff:g id="VPN_APP">%1$s</xliff:g> bidez daude konektatuta Internetera. IKT saileko administratzaileak eta VPNaren hornitzaileak laneko aplikazioen bidez egiten dituzun sareko jarduerak (mezu elektronikoak eta arakatze-datuak barne) ikusi ahalko dituzte."</string>
<string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Aplikazio pertsonalak <xliff:g id="VPN_APP">%1$s</xliff:g> bidez daude konektatuta Internetera. IKT saileko administratzaileak sareko jarduerak (mezu elektronikoak eta arakatze-datuak barne) ikusi ahalko ditu."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
- <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Ireki VPN ezarpenak"</string>
+ <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Ireki VPN sarearen ezarpenak"</string>
<string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Zure gurasoak kudeatzen du gailua. Zure gurasoak gailuko informazioa ikusi eta kudea dezake; besteak beste, zer aplikazio erabiltzen dituzun, zure kokapena zein den eta pantaila aurrean zenbat eta noiz egoten zaren."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPNa"</string>
<string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent bidez desblokeatuta"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 06a14f2..5676865 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -78,7 +78,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"دوباره نماگرفت بگیرید"</string>
<string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"نماگرفت ذخیره نمیشود"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"برنامه یا سازمان شما اجازه نمیدهند نماگرفت بگیرید."</string>
- <string name="screenshot_blocked_by_admin" msgid="5486757604822795797">"سرپرست سیستم گرفتن نماگرفت را مسدود کرده است"</string>
+ <string name="screenshot_blocked_by_admin" msgid="5486757604822795797">"سرپرست فناوری اطلاعات گرفتن نماگرفت را مسدود کرده است"</string>
<string name="screenshot_edit_label" msgid="8754981973544133050">"ویرایش"</string>
<string name="screenshot_edit_description" msgid="3333092254706788906">"ویرایش نماگرفت"</string>
<string name="screenshot_share_description" msgid="2861628935812656612">"همرسانی نماگرفت"</string>
@@ -353,10 +353,10 @@
<string name="user_remove_user_title" msgid="9124124694835811874">"کاربر حذف شود؟"</string>
<string name="user_remove_user_message" msgid="6702834122128031833">"همه برنامهها و دادههای این کاربر حذف میشود."</string>
<string name="user_remove_user_remove" msgid="8387386066949061256">"حذف"</string>
- <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> به همه اطلاعاتی که روی صفحهنمایش قابلمشاهد است و هنگام ضبط کردن یا ارسال محتوا از دستگاهتان پخش میشود دسترسی خواهد داشت. این شامل اطلاعاتی مانند گذرواژهها، جزئیات پرداخت، عکسها، پیامها، و صداهایی که پخش میکنید میشود."</string>
- <string name="media_projection_dialog_service_text" msgid="958000992162214611">"سرویس ارائهدهنده این عملکرد به همه اطلاعاتی که روی صفحهنمایش قابلمشاهد است و هنگام ضبط کردن یا ارسال محتوا از دستگاهتان پخش میشود دسترسی خواهد داشت. این شامل اطلاعاتی مانند گذرواژهها، جزئیات پرداخت، عکسها، پیامها، و صداهایی که پخش میکنید میشود."</string>
- <string name="media_projection_dialog_service_title" msgid="2888507074107884040">"ضبط یا ارسال محتوا شروع شود؟"</string>
- <string name="media_projection_dialog_title" msgid="3316063622495360646">"ضبط یا ارسال محتوا با <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> شروع شود؟"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> به همه اطلاعاتی که روی صفحهنمایش قابلمشاهد است و هنگام ضبط کردن یا پخش محتوا از دستگاهتان پخش میشود دسترسی خواهد داشت. این شامل اطلاعاتی مانند گذرواژهها، جزئیات پرداخت، عکسها، پیامها، و صداهایی که پخش میکنید میشود."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"سرویس ارائهدهنده این عملکرد به همه اطلاعاتی که روی صفحهنمایش قابلمشاهد است و هنگام ضبط کردن یا پخش محتوا از دستگاهتان پخش میشود دسترسی خواهد داشت. این شامل اطلاعاتی مانند گذرواژهها، جزئیات پرداخت، عکسها، پیامها، و صداهایی که پخش میکنید میشود."</string>
+ <string name="media_projection_dialog_service_title" msgid="2888507074107884040">"ضبط یا پخش محتوا شروع شود؟"</string>
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"ضبط یا پخش محتوا با <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> شروع شود؟"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"پاک کردن همه موارد"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"مدیریت"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"سابقه"</string>
@@ -380,7 +380,7 @@
<string name="quick_settings_disclosure_named_management_vpns" msgid="3312645578322079185">"این دستگاه متعلق به <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> است و ازطریق چند VPN به اینترنت متصل شده است"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"ممکن است سازمان شما ترافیک شبکه را در نمایه کاریتان پایش کند"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ممکن است ترافیک شبکه را در نمایه کاری شما پایش کند"</string>
- <string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"سرپرست سیستم میتواند فعالیت شبکه نمایه کاری را ببیند"</string>
+ <string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"سرپرست فناوری اطلاعات میتواند فعالیت شبکه نمایه کاری را ببیند"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"ممکن است شبکه پایش شود"</string>
<string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"این دستگاه ازطریق چند VPN به اینترنت متصل شده است"</string>
<string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"برنامههای کاریتان ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g> به اینترنت متصل شده است"</string>
@@ -401,9 +401,9 @@
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"مرجع گواهینامهای در این دستگاه نصب شده است. ممکن است ترافیک امن شبکه شما پایش یا تغییر داده شود."</string>
<string name="monitoring_description_management_network_logging" msgid="216983105036994771">"سرپرست سیستم شما گزارشگیری از شبکه را (که ترافیک دستگاه شما را پایش میکند) روشن کرده است."</string>
<string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"سرپرست شما گزارشگیری شبکه را که بر ترافیک نمایه کاریتان نظارت میکند، اما بر ترافیک نمایه شخصیتان نظارت نمیکند روشن کرده است."</string>
- <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"این دستگاه ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g> به اینترنت متصل شده است. سرپرست سیستم شما میتواند فعالیت شبکه شما را (ازجمله ایمیلها و دادههای مرور) ببیند."</string>
- <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"این دستگاه ازطریق <xliff:g id="VPN_APP_0">%1$s</xliff:g> و <xliff:g id="VPN_APP_1">%2$s</xliff:g> به اینترنت متصل شده است. سرپرست سیستم شما میتواند فعالیت شبکه شما را (ازجمله ایمیلها و دادههای مرور) ببیند."</string>
- <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"برنامههای کاریتان ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g> به اینترنت متصل شده است. ارائهدهنده VPN و سرپرست سیستم شما میتوانند فعالیت شبکه شما در برنامههای کاری را (ازجمله ایمیلها و دادههای مرور) ببینند."</string>
+ <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"این دستگاه ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g> به اینترنت متصل شده است. سرپرست فناوری اطلاعات شما میتواند فعالیت شبکه شما را (ازجمله ایمیلها و دادههای مرور) ببیند."</string>
+ <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"این دستگاه ازطریق <xliff:g id="VPN_APP_0">%1$s</xliff:g> و <xliff:g id="VPN_APP_1">%2$s</xliff:g> به اینترنت متصل شده است. سرپرست فناوری اطلاعات شما میتواند فعالیت شبکه شما را (ازجمله ایمیلها و دادههای مرور) ببیند."</string>
+ <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"برنامههای کاریتان ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g> به اینترنت متصل شده است. ارائهدهنده VPN و سرپرست فناوری اطلاعات شما میتوانند فعالیت شبکه شما در برنامههای کاری را (ازجمله ایمیلها و دادههای مرور) ببینند."</string>
<string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"برنامههای شخصیتان ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g> به اینترنت متصل شده است. ارائهدهنده VPN شما میتواند فعالیت شبکه شما را (ازجمله ایمیلها و دادههای مرور) ببیند."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
<string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"باز کردن تنظیمات VPN"</string>
@@ -553,7 +553,7 @@
<string name="keyboard_key_dpad_right" msgid="6282105433822321767">"راست"</string>
<string name="keyboard_key_dpad_center" msgid="4079412840715672825">"مرکز"</string>
<string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
- <string name="keyboard_key_space" msgid="6980847564173394012">"فاصله"</string>
+ <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
<string name="keyboard_key_enter" msgid="8633362970109751646">"ورود"</string>
<string name="keyboard_key_backspace" msgid="4095278312039628074">"پسبر"</string>
<string name="keyboard_key_media_play_pause" msgid="8389984232732277478">"پخش/مکث"</string>
@@ -843,7 +843,7 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"مرتبط کردن دستگاه جدید"</string>
<string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"برای ارسال محتوای این جلسه، لطفاً برنامه را باز کنید."</string>
<string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"برنامه ناشناس"</string>
- <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"توقف ارسال محتوا"</string>
+ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"توقف پخش محتوا"</string>
<string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"دستگاههای دردسترس برای خروجی صدا."</string>
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"میزان صدا"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"همهفرتستی چطور کار میکند"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"نوشتار کپی شد"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"تصویر کپی شد"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"محتوا کپی شد"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"ویرایشگر بریدهدان"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"بریدهدان"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"پیشنمای تصویر"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"ویرایش کردن"</string>
<string name="add" msgid="81036585205287996">"افزودن"</string>
<string name="manage_users" msgid="1823875311934643849">"مدیریت کاربران"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"این اعلان از تنظیم کشیدن برای دو نیمه کردن صفحه پشتیبانی نمیکند."</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index c811d22..d1cdb9f 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Teksti kopioitu"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Kuva kopioitu"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Sisältö kopioitu"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Leikepöydän muokkaaja"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Leikepöytä"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Kuvan esikatselu"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"muokkaa"</string>
<string name="add" msgid="81036585205287996">"Lisää"</string>
<string name="manage_users" msgid="1823875311934643849">"Ylläpidä käyttäjiä"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Ilmoitus ei tue jaetulle näytölle vetämistä."</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 1c72886..db37f77 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Texte copié"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Image copiée"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Contenu copié"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Éditeur du presse-papiers"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Presse-papiers"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Aperçu de l\'image"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"modifier"</string>
<string name="add" msgid="81036585205287996">"Ajouter"</string>
<string name="manage_users" msgid="1823875311934643849">"Gérer les utilisateurs"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Cette notification ne prend pas en charge le partage d\'écran par glissement."</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index d0d781f..dc708e8 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Texte copié"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Image copiée"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Contenu copié"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Éditeur du presse-papiers"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Presse-papiers"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Aperçu de l\'image"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"modifier"</string>
<string name="add" msgid="81036585205287996">"Ajouter"</string>
<string name="manage_users" msgid="1823875311934643849">"Gérer les utilisateurs"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Impossible de faire glisser cette notification vers l\'écran partagé."</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 1718992..e648918 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Texto copiado"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Imaxe copiada"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Contido copiado"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor do portapapeis"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Portapapeis"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Vista previa da imaxe"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"editar"</string>
<string name="add" msgid="81036585205287996">"Engadir"</string>
<string name="manage_users" msgid="1823875311934643849">"Xestionar usuarios"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Esta notificación non pode arrastrarse á pantalla dividida."</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 4fc3843..c015403 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"કૅમેરા"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ફોન"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"વૉઇસ સહાય"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"વૉલેટ"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR કોડ સ્કૅનર"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"અનલૉક કરો"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"ડિવાઇસ લૉક કરેલું છે"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"ડેમો મોડ બતાવો"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"ઇથરનેટ"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"અલાર્મ"</string>
- <string name="wallet_title" msgid="5369767670735827105">"વૉલેટ"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"તમારા ફોન વડે વધુ ઝડપી તેમજ સુરક્ષિત ખરીદીઓ કરવાની રીત સેટઅપ કરી લો"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"બધું બતાવો"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"ખોલવા માટે ટૅપ કરો"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"ટેક્સ્ટ કૉપિ કરી"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"છબી કૉપિ કરી"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"કન્ટેન્ટ કૉપિ કર્યું"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"ક્લિપબોર્ડ એડિટર"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"ક્લિપબોર્ડ"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"છબીનો પ્રીવ્યૂ"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"ફેરફાર કરો"</string>
<string name="add" msgid="81036585205287996">"ઉમેરો"</string>
<string name="manage_users" msgid="1823875311934643849">"વપરાશકર્તાઓને મેનેજ કરો"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"આ નોટિફિકેશન તેને સ્પ્લિટસ્ક્રીનમાં ખેંચવાની સુવિધાને સપોર્ટ કરતું નથી."</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 440b376..f2ff6d8 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"कैमरा"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"फ़ोन"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"आवाज़ से डिवाइस का इस्तेमाल"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"वॉलेट बटन"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"क्यूआर कोड स्कैनर"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"अनलॉक करें"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"डिवाइस लॉक है"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"डेमो मोड दिखाएं"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"ईथरनेट"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"अलार्म"</string>
- <string name="wallet_title" msgid="5369767670735827105">"वॉलेट"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"फ़ोन के ज़रिए तेज़ी से और सुरक्षित तरीके से खरीदारी करने के लिए सेट अप करें"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"सभी दिखाएं"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"अनलॉक करने के लिए टैप करें"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"टेक्स्ट कॉपी किया गया"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"इमेज कॉपी की गई"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"कॉन्टेंट कॉपी किया गया"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"क्लिपबोर्ड एडिटर"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"क्लिपबोर्ड"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"इमेज की झलक"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"बदलाव करें"</string>
<string name="add" msgid="81036585205287996">"जोड़ें"</string>
<string name="manage_users" msgid="1823875311934643849">"उपयोगकर्ताओं को मैनेज करें"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"इस सूचना को स्प्लिट स्क्रीन मोड में, खींचा और छोड़ा नहीं जा सकता."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 330363a..e34a08e 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -465,7 +465,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"Prikaži demo način"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
- <string name="wallet_title" msgid="5369767670735827105">"Novčanik"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"Postavite aplikaciju za bržu i sigurniju kupnju telefonom"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Prikaži sve"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Dodirnite za otvaranje"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index c2e2ace..271b1eb 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Szöveg másolva"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Kép másolva"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Tartalom másolva"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Vágólapszerkesztő"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Vágólap"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Kép előnézete"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"szerkesztés"</string>
<string name="add" msgid="81036585205287996">"Hozzáadás"</string>
<string name="manage_users" msgid="1823875311934643849">"Felhasználók kezelése"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Az értesítés nem támogatja a megosztott képernyőre való áthúzást."</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 6c97321..1c8a351 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Տեքստը պատճենվեց"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Պատկերը պատճենվեց"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Բովանդակությունը պատճենվեց"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Սեղմատախտակի խմբագրիչ"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Սեղմատախտակ"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Պատկերի նախադիտում"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"փոփոխել"</string>
<string name="add" msgid="81036585205287996">"Ավելացնել"</string>
<string name="manage_users" msgid="1823875311934643849">"Օգտատերերի կառավարում"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Այս ծանուցումը հնարավոր չէ քաշել տրոհված էկրանի մեկ հատվածից մյուսը։"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 0eb5ef3..cf36c60 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Teks disalin"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Gambar disalin"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Konten disalin"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor Papan Klip"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Papan klip"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Pratinjau gambar"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"mengedit"</string>
<string name="add" msgid="81036585205287996">"Tambahkan"</string>
<string name="manage_users" msgid="1823875311934643849">"Kelola pengguna"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Notifikasi ini tidak mendukung fitur tarik ke Layar terpisah."</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 372dd1c..c786d0d 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Texti afritaður"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Mynd afrituð"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Efni afritað"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Klippiborðsritill"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Klippiborð"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Forskoðun myndar"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"breyta"</string>
<string name="add" msgid="81036585205287996">"Bæta við"</string>
<string name="manage_users" msgid="1823875311934643849">"Stjórna notendum"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Þessi tilkynning styður ekki að draga yfir á skiptan skjá."</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index e0af998..7065f7f 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Testo copiato"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Immagine copiata"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Contenuti copiati"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor di appunti"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Appunti"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Anteprima immagine"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"modificare"</string>
<string name="add" msgid="81036585205287996">"Aggiungi"</string>
<string name="manage_users" msgid="1823875311934643849">"Gestisci utenti"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Non è possibile trascinare questa notifica tra le due parti dello schermo diviso."</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 8b45531..aa8f6cb 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -468,7 +468,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"הצגת מצב הדגמה"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"אתרנט"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"התראה"</string>
- <string name="wallet_title" msgid="5369767670735827105">"ארנק"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"מגדירים אמצעי תשלום ונהנים מביצוע מהיר ומאובטח יותר של רכישות באמצעות הטלפון"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"הצגת הכול"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"יש להקיש לפתיחה"</string>
@@ -959,14 +959,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"הטקסט הועתק"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"התמונה הועתקה"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"התוכן הועתק"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"עורך הלוח"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"לוח"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"תצוגה מקדימה של תמונה"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"עריכה"</string>
<string name="add" msgid="81036585205287996">"הוספה"</string>
<string name="manage_users" msgid="1823875311934643849">"ניהול משתמשים"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ההתראה הזו לא תומכת בגרירה למסך מפוצל."</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index b0171de..20bdf5f 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Мәтін көшірілді."</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Сурет көшірілді."</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Мазмұн көшірілді."</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Буфер редакторы"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Буфер"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Суретті алдын ала көру"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"өзгерту"</string>
<string name="add" msgid="81036585205287996">"Қосу"</string>
<string name="manage_users" msgid="1823875311934643849">"Пайдаланушыларды басқару"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Бұл хабарландыруды бөлінген экранға сүйреп апару мүмкін емес."</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 9aacc3b..eb2f68d 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"បានចម្លងអត្ថបទ"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"បានចម្លងរូបភាព"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"បានចម្លងខ្លឹមសារ"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"កម្មវិធីកែឃ្លីបបត"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"ឃ្លីបបត"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"មើលរូបភាពសាកល្បង"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"កែ"</string>
<string name="add" msgid="81036585205287996">"បញ្ចូល"</string>
<string name="manage_users" msgid="1823875311934643849">"គ្រប់គ្រងអ្នកប្រើប្រាស់"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ការជូនដំណឹងនេះមិនអាចឱ្យអូសដើម្បីបំបែកអេក្រង់បានទេ។"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 6aef3bd..8198d7f 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"ಕ್ಯಾಮರಾ"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ಫೋನ್"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ಧ್ವನಿ ಸಹಾಯಕ"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"ವಾಲೆಟ್"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR ಕೋಡ್ ಸ್ಕ್ಯಾನರ್"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"ಅನ್ಲಾಕ್"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"ಸಾಧನ ಲಾಕ್ ಆಗಿದೆ"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"ಪಠ್ಯವನ್ನು ನಕಲಿಸಲಾಗಿದೆ"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"ಚಿತ್ರವನ್ನು ನಕಲಿಸಲಾಗಿದೆ"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"ವಿಷಯವನ್ನು ನಕಲಿಸಲಾಗಿದೆ"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"ಕ್ಲಿಪ್ಬೋರ್ಡ್ ಎಡಿಟರ್"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"ಕ್ಲಿಪ್ಬೋರ್ಡ್"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"ಚಿತ್ರದ ಪೂರ್ವವೀಕ್ಷಣೆ"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"ಎಡಿಟ್ ಮಾಡಿ"</string>
<string name="add" msgid="81036585205287996">"ಸೇರಿಸಿ"</string>
<string name="manage_users" msgid="1823875311934643849">"ಬಳಕೆದಾರರನ್ನು ನಿರ್ವಹಿಸಿ"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ಗೆ ಡ್ರ್ಯಾಗ್ ಮಾಡುವುದನ್ನು ಈ ಅಧಿಸೂಚನೆಯು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ."</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 899bca3..b14e9e8 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"텍스트 복사됨"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"이미지 복사됨"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"콘텐츠 복사됨"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"클립보드 편집기"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"클립보드"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"이미지 미리보기"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"수정"</string>
<string name="add" msgid="81036585205287996">"추가"</string>
<string name="manage_users" msgid="1823875311934643849">"사용자 관리"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"드래그하여 화면을 분할하는 기능이 지원되지 않는 알림입니다."</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index deaeb43..11cdc7d 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"Демо режимин көрсөтүү"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Ойготкуч"</string>
- <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Капчык"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"Телефонуңуз менен тез жана коопсуз сатып алуу үчүн жөндөңүз"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Баарын көрсөтүү"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Ачуу үчүн таптап коюңуз"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Текст көчүрүлдү"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Сүрөт көчүрүлдү"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Мазмун көчүрүлдү"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Алмашуу буферин түзөткүч"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Алмашуу буфери"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Сүрөттү алдын ала көрүү"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"түзөтүү"</string>
<string name="add" msgid="81036585205287996">"Кошуу"</string>
<string name="manage_users" msgid="1823875311934643849">"Колдонуучуларды башкаруу"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Бул билдирмени бөлүнгөн экранда сүйрөөгө болбойт."</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 780e4c7..cb86e04 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"ກ້ອງ"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ໂທລະສັບ"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ຊ່ວຍເຫຼືອທາງສຽງ"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"ກະເປົາ"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"ຕົວສະແກນລະຫັດ QR"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"ປົດລັອກ"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"ອຸປະກອນຖືກລັອກໄວ້"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"ສະແດງໂຫມດສາທິດ"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"ອີເທເນັດ"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"ໂມງປຸກ"</string>
- <string name="wallet_title" msgid="5369767670735827105">"ກະເປົາ"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"ຕັ້ງຄ່າເພື່ອຊື້ດ້ວຍໂທລະສັບຂອງທ່ານໄດ້ໄວຂຶ້ນ ແລະ ປອດໄພຂຶ້ນ"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"ສະແດງທັງໝົດ"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"ແຕະເພື່ອເປີດ"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"ສຳເນົາຂໍ້ຄວາມແລ້ວ"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"ສຳເນົາຮູບແລ້ວ"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"ສຳເນົາເນື້ອຫາແລ້ວ"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"ຕົວແກ້ໄຂຄລິບບອດ"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"ຄລິບບອດ"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"ຕົວຢ່າງຮູບ"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"ແກ້ໄຂ"</string>
<string name="add" msgid="81036585205287996">"ເພີ່ມ"</string>
<string name="manage_users" msgid="1823875311934643849">"ຈັດການຜູ້ໃຊ້"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ການແຈ້ງເຕືອນນີ້ບໍ່ຮອງຮັບການລາກໄປໃສ່ Splitscreen."</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index b4d5bca..0df0af2 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Fotoaparatas"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefonas"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"Piniginė"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR kodų skaitytuvas"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Atrakinti"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Įrenginys užrakintas"</string>
@@ -468,7 +468,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"Rodyti demonstraciniu režimu"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Eternetas"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Signalas"</string>
- <string name="wallet_title" msgid="5369767670735827105">"Piniginė"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"Nustatykite, kad galėtumėte greičiau ir saugiau pirkti telefonu"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Rodyti viską"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Palieskite, kad atidarytumėte"</string>
@@ -959,14 +959,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Tekstas nukopijuotas"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Vaizdas nukopijuotas"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Turinys nukopijuotas"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Iškarpinės redagavimo priemonė"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Iškarpinė"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Vaizdo peržiūra"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"redaguoti"</string>
<string name="add" msgid="81036585205287996">"Pridėti"</string>
<string name="manage_users" msgid="1823875311934643849">"Tvarkyti naudotojus"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Šio pranešimo vilkimas išskaidyto ekrano režimu nepalaikomas."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index a74447a..93824c8 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -952,14 +952,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Teksts ir nokopēts"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Attēls ir nokopēts"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Saturs ir nokopēts"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Starpliktuves redaktors"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Starpliktuve"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Attēla priekšskatījums"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"rediģētu"</string>
<string name="add" msgid="81036585205287996">"Pievienot"</string>
<string name="manage_users" msgid="1823875311934643849">"Pārvaldīt lietotājus"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Šis paziņojums neatbalsta vilkšanu uz dalīto ekrānu."</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 68afb04..093b2a3 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -402,7 +402,7 @@
<string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Вашиот администратор вклучил евиденција на мрежата, што подразбира следење на сообраќајот на вашиот уред."</string>
<string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Вашиот администратор вклучил мрежна евиденција, што подразбира следење на сообраќајот во работниот, но не и во личниот профил."</string>
<string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Уредов е поврзан на интернет преку <xliff:g id="VPN_APP">%1$s</xliff:g>. Вашата мрежна активност во работните апликации, вклучително е-пораките и податоците од прелистување, е видлива за вашиот IT-администратор."</string>
- <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Уредот е поврзан на интернет преку <xliff:g id="VPN_APP_0">%1$s</xliff:g> и <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Вашата мрежна активност во работните апликации, вклучително е-пораките и податоците од прелистување, е видлива за вашиот IT-администратор."</string>
+ <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Уредот е поврзан на интернет преку <xliff:g id="VPN_APP_0">%1$s</xliff:g> и <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Вашата мрежна активност, вклучително е-пораките и податоците од прелистување, е видлива за IT-администраторот."</string>
<string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Вашите работни апликации се поврзани на интернет преку <xliff:g id="VPN_APP">%1$s</xliff:g>. Вашата мрежна активност во работните апликации, вклучително е-пораките и податоците од прелистување, е видлива за вашиот IT-администратор и давател на услуги за VPN."</string>
<string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Вашите лични апликации се поврзани на интернет преку <xliff:g id="VPN_APP">%1$s</xliff:g>. Вашата мрежна активност во работните апликации, вклучително е-пораките и податоците од прелистување, е видлива за вашиот давател на услуги за VPN."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Текстот е копиран"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Сликата е копирана"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Содржините се копирани"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Уредувач на привремена меморија"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Привремена меморија"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Преглед на сликата"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"измени"</string>
<string name="add" msgid="81036585205287996">"Додај"</string>
<string name="manage_users" msgid="1823875311934643849">"Управувајте со корисниците"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Известувањево не поддржува влечење на поделен екран."</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index b453c8c..2fa1640 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Камер"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Утас"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Дуут туслах"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"Түрийвч"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR код сканнер"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Тайлах"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Төхөөрөмжийг түгжсэн"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"Демо горимыг харуулах"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Этернет"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Сэрүүлэг"</string>
- <string name="wallet_title" msgid="5369767670735827105">"Түрийвч"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"Утсаараа илүү хурдан, аюулгүй худалдан авалт хийхийн тулд тохируулгыг авна уу"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Бүгдийг харуулах"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Нээх бол товшино уу"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 1d303eb..835d085 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"मजकूर कॉपी केला"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"इमेज कॉपी केली"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"आशय कॉपी केला"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"क्लिपबोर्ड संपादक"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"क्लिपबोर्ड"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"इमेजचे पूर्वावलोकन"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"संपादित करा"</string>
<string name="add" msgid="81036585205287996">"जोडा"</string>
<string name="manage_users" msgid="1823875311934643849">"वापरकर्ते व्यवस्थापित करा"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ही सूचना स्प्लिटस्क्रीनवर ड्रॅग करण्याला सपोर्ट करत नाही."</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 7782443..c4f30e5 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Teks disalin"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Imej disalin"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Kandungan disalin"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor Papan Klip"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Papan klip"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Pratonton imej"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"edit"</string>
<string name="add" msgid="81036585205287996">"Tambah"</string>
<string name="manage_users" msgid="1823875311934643849">"Urus pengguna"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Pemberitahuan ini tidak menyokong penyeretan ke Skrin pisah."</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index ed509e2..ae0eb50 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -90,7 +90,7 @@
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ဘယ်ဘက်အနားသတ် <xliff:g id="PERCENT">%1$d</xliff:g> ရာခိုင်နှုန်း"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ညာဘက်အနားသတ် <xliff:g id="PERCENT">%1$d</xliff:g> ရာခိုင်နှုန်း"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"ဖန်သားပြင် ရိုက်ကူးမှု"</string>
- <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ဖန်သားပြင်ရိုက်ကူးနေသည်"</string>
+ <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"စကရင်ရိုက်ကူးမှု အပြီးသတ်နေသည်"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ဖန်သားပြင် ရိုက်ကူးသည့် စက်ရှင်အတွက် ဆက်တိုက်လာနေသော အကြောင်းကြားချက်"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"စတင် ရိုက်ကူးမလား။"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"ရိုက်ကူးနေစဉ်အတွင်း Android စနစ်သည် သင့်ဖန်သားပြင်ပေါ်တွင် မြင်နိုင်သော (သို့) သင့်စက်ပစ္စည်းတွင် ဖွင့်ထားသော အရေးကြီးသည့် အချက်အလက်များကို ရိုက်ယူနိုင်သည်။ ၎င်းတွင် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ ဓာတ်ပုံ၊ မက်ဆေ့ဂျ်နှင့် အသံများ ပါဝင်သည်။"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"စာသားကို မိတ္တူကူးပြီးပြီ"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"ပုံ ကူးပြီးပြီ"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"အကြောင်းအရာများကို ကူးယူပြီးပါပြီ"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"ကလစ်ဘုတ် တည်းဖြတ်စနစ်"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"ကလစ်ဘုတ်"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"ပုံအစမ်းကြည့်ခြင်း"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"တည်းဖြတ်ရန်"</string>
<string name="add" msgid="81036585205287996">"ထည့်ရန်"</string>
<string name="manage_users" msgid="1823875311934643849">"အသုံးပြုသူများ စီမံရန်"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ဤအကြောင်းကြားချက်သည် ‘မျက်နှာပြင်ခွဲ၍ပြသမှု’ သို့ ဖိဆွဲခြင်းကို မပံ့ပိုးပါ။"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 5f3bc0a..e6324f4 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Teksten er kopiert"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Bildet er kopiert"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Innholdet er kopiert"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Utklippstavleredigerer"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Utklippstavle"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Forhåndsvisning av bilde"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"redigere"</string>
<string name="add" msgid="81036585205287996">"Legg til"</string>
<string name="manage_users" msgid="1823875311934643849">"Administrer brukere"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Dette varselet støtter ikke at du drar det til en delt skjerm."</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index c9c5b06..a18cae4 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"क्यामेरा"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"फोन"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"आवाज सहायता"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"वालेट"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR कोड स्क्यानर"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"खोल्नुहोस्"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"यन्त्र लक गरिएको छ"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"डेमो मोड देखाउनुहोस्"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"इथरनेट"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"अलार्म"</string>
- <string name="wallet_title" msgid="5369767670735827105">"वालेट"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"फोनमार्फत अझ छिटो र थप सुरक्षित तरिकाले खरिद गर्न भुक्तानी विधि सेटअप गर्नुहोस्"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"सबै देखाइयोस्"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"खोल्न ट्याप गर्नुहोस्"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"टेक्स्ट कपी गरिएको छ"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"फोटो कपी गरिएको छ"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"सामग्री कपी गरिएको छ"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"क्लिपबोर्ड एडिटर"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"क्लिपबोर्ड"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"फोटोको प्रिभ्यू"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"सम्पादन गर्नुहोस्"</string>
<string name="add" msgid="81036585205287996">"हाल्नुहोस्"</string>
<string name="manage_users" msgid="1823875311934643849">"प्रयोगकर्ताहरूको व्यवस्थापन गर्नुहोस्"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"यो सूचना ड्र्याग गरेर स्प्लिटस्क्रिनमा लैजान मिल्दैन।"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 15d1615..eaa4ca1 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Tekst gekopieerd"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Afbeelding gekopieerd"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Content gekopieerd"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Klembordeditor"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Klembord"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Afbeeldingsvoorbeeld"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"bewerken"</string>
<string name="add" msgid="81036585205287996">"Toevoegen"</string>
<string name="manage_users" msgid="1823875311934643849">"Gebruikers beheren"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Deze melding biedt geen ondersteuning voor slepen naar het gesplitste scherm."</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index f532830..99243d2 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"ଟେକ୍ସଟ କପି କରାଯାଇଛି"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"ଇମେଜ କପି କରାଯାଇଛି"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"ବିଷୟବସ୍ତୁ କପି କରାଯାଇଛି"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"କ୍ଲିପବୋର୍ଡ ଏଡିଟର"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"କ୍ଲିପବୋର୍ଡ"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"ଇମେଜ ପ୍ରିଭ୍ୟୁ"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"ଏଡିଟ"</string>
<string name="add" msgid="81036585205287996">"ଯୋଗ କରନ୍ତୁ"</string>
<string name="manage_users" msgid="1823875311934643849">"ଉପଯୋଗକର୍ତ୍ତାମାନଙ୍କୁ ପରିଚାଳନା କରନ୍ତୁ"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ଏହି ବିଜ୍ଞପ୍ତି ସ୍ପ୍ଲିଟସ୍କ୍ରିନକୁ ଡ୍ରାଗ କରିବାକୁ ସମର୍ଥନ କରେ ନାହିଁ।"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 60bc19e..a4631d8 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -959,14 +959,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Tekst został skopiowany"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Zdjęcie zostało skopiowane"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Treści zostały skopiowane"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Edytor schowka"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Schowek"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Podgląd obrazu"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"edytować"</string>
<string name="add" msgid="81036585205287996">"Dodaj"</string>
<string name="manage_users" msgid="1823875311934643849">"Zarządzaj użytkownikami"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"To powiadomienie nie obsługuje dzielenia ekranu przez przeciąganie."</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index cd69f86..09591cb 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -384,8 +384,8 @@
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"A rede pode ser monitorada"</string>
<string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"Este dispositivo está conectado à Internet usando VPNs"</string>
<string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"Seus apps de trabalho estão conectados à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
- <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="451254750289172191">"Seus apps pessoais estão conectados à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
- <string name="quick_settings_disclosure_named_vpn" msgid="6191822916936028208">"Este dispositivo está conectado à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="451254750289172191">"Apps pessoais conectados à Internet via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="6191822916936028208">"Conectado à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_financed_device" msgid="3659962357973919387">"Este dispositivo é fornecido pela <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Gerenciamento de dispositivos"</string>
<string name="monitoring_subtitle_vpn" msgid="800485258004629079">"VPN"</string>
@@ -404,7 +404,7 @@
<string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Este dispositivo está conectado à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>. Suas atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o administrador de TI."</string>
<string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Seu dispositivo está conectado à Internet usando o <xliff:g id="VPN_APP_0">%1$s</xliff:g> e <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Suas atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o administrador de TI."</string>
<string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Seus apps de trabalho estão conectados à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>. Suas atividades de rede em apps de trabalho, incluindo e-mails e dados de navegação, estão visíveis para o administrador de TI e o provedor de VPN."</string>
- <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Seus apps pessoais estão conectados à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>. Suas atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o provedor de VPN."</string>
+ <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Seus apps pessoais estão conectados à Internet via <xliff:g id="VPN_APP">%1$s</xliff:g>. As atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o provedor de VPN."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
<string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Abrir configurações de VPN"</string>
<string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerenciado pelo seu pai/mãe, que pode ver e gerenciar informações como os apps que você usa, sua localização e seu tempo de uso."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index cd69f86..09591cb 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -384,8 +384,8 @@
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"A rede pode ser monitorada"</string>
<string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"Este dispositivo está conectado à Internet usando VPNs"</string>
<string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"Seus apps de trabalho estão conectados à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
- <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="451254750289172191">"Seus apps pessoais estão conectados à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
- <string name="quick_settings_disclosure_named_vpn" msgid="6191822916936028208">"Este dispositivo está conectado à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="451254750289172191">"Apps pessoais conectados à Internet via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="6191822916936028208">"Conectado à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_financed_device" msgid="3659962357973919387">"Este dispositivo é fornecido pela <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7029691083837606324">"Gerenciamento de dispositivos"</string>
<string name="monitoring_subtitle_vpn" msgid="800485258004629079">"VPN"</string>
@@ -404,7 +404,7 @@
<string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Este dispositivo está conectado à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>. Suas atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o administrador de TI."</string>
<string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Seu dispositivo está conectado à Internet usando o <xliff:g id="VPN_APP_0">%1$s</xliff:g> e <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Suas atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o administrador de TI."</string>
<string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Seus apps de trabalho estão conectados à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>. Suas atividades de rede em apps de trabalho, incluindo e-mails e dados de navegação, estão visíveis para o administrador de TI e o provedor de VPN."</string>
- <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Seus apps pessoais estão conectados à Internet usando o <xliff:g id="VPN_APP">%1$s</xliff:g>. Suas atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o provedor de VPN."</string>
+ <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Seus apps pessoais estão conectados à Internet via <xliff:g id="VPN_APP">%1$s</xliff:g>. As atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o provedor de VPN."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
<string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Abrir configurações de VPN"</string>
<string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerenciado pelo seu pai/mãe, que pode ver e gerenciar informações como os apps que você usa, sua localização e seu tempo de uso."</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 961798e..19a2bb9 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -952,14 +952,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Textul a fost copiat"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Imaginea a fost copiată"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Conținutul a fost copiat"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor de clipboard"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Clipboard"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Previzualizarea imaginii"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"editați"</string>
<string name="add" msgid="81036585205287996">"Adăugați"</string>
<string name="manage_users" msgid="1823875311934643849">"Gestionați utilizatorii"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Notificarea nu acceptă tragerea pe ecranul împărțit."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index d088357..bd907ef 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -959,14 +959,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Текст скопирован"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Изображение скопировано"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Данные скопированы"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Редактор буфера обмена"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Буфер обмена"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Предварительный просмотр изображения"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"изменить"</string>
<string name="add" msgid="81036585205287996">"Добавить"</string>
<string name="manage_users" msgid="1823875311934643849">"Управление пользователями"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Это уведомление нельзя перетаскивать между частями разделенного экрана."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 7d9944f..13795a3 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"පෙළ පිටපත් කරන ලදී"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"රූපය පිටපත් කරන ලදි"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"අන්තර්ගතය පිටපත් කරන ලදි"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"පසුරු පුවරු සංස්කාරක"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"පසුරු පුවරුව"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"රූප පෙරදසුන"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"සංස්කරණය"</string>
<string name="add" msgid="81036585205287996">"එක් කරන්න"</string>
<string name="manage_users" msgid="1823875311934643849">"පරිශීලකයන් කළමනාකරණය කරන්න"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"මෙම දැනුම්දීම බෙදුම් තිරය වෙත ඇද ගෙන යාමට සහාය නොදක්වයි."</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index a6868d5..8ec4eef 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -959,14 +959,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Besedilo je kopirano"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Slika je kopirana"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Vsebina je kopirana"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Urejevalnik odložišča"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Odložišče"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Predogled slike"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"urejanje"</string>
<string name="add" msgid="81036585205287996">"Dodaj"</string>
<string name="manage_users" msgid="1823875311934643849">"Upravljanje uporabnikov"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"To obvestilo ne podpira vlečenja v razdeljen zaslon."</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 2834960..c6a06bb 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"Telefoni"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ndihma zanore"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portofoli"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Skaneri i kodeve QR"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"Shkyç"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"Pajisja është e kyçur"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"Shfaq modalitetin e demonstrimit"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Eternet"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"Alarmi"</string>
- <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"Portofoli"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"Konfiguro për të kryer pagesa më të shpejta dhe më të sigurta përmes telefonit"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Shfaqi të gjitha"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Trokit për ta hapur"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Teksti u kopjua"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Imazhi u kopjua"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Përmbajtja u kopjua"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Modifikuesi i \"Kujtesës së fragmenteve\""</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Kujtesa e fragmenteve"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Pamja paraprake e imazhit"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"për të modifikuar"</string>
<string name="add" msgid="81036585205287996">"Shto"</string>
<string name="manage_users" msgid="1823875311934643849">"Menaxho përdoruesit"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Ky njoftim nuk mbështet zvarritjen në \"Ekranin e ndarë\"."</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index f0d7f84..50299de 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -952,14 +952,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Текст је копиран"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Слика је копирана"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Садржај је копиран"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Уређивач привремене меморије"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Привремена меморија"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Преглед слике"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"измените"</string>
<string name="add" msgid="81036585205287996">"Додај"</string>
<string name="manage_users" msgid="1823875311934643849">"Управљаjте корисницима"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Ово обавештење не подржава превлачење на подељени екран."</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index c45b1e5..12bf290 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Texten har kopierats"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Bilden har kopierats"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Innehållet har kopierats"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Redigerare för urklipp"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Urklipp"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Bildförhandsgranskning"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"redigera"</string>
<string name="add" msgid="81036585205287996">"Lägg till"</string>
<string name="manage_users" msgid="1823875311934643849">"Hantera användare"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Det går inte att dra den här aviseringen till delad skärm."</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index c462c34..25543fe 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Maandishi yamenakiliwa"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Picha imenakiliwa"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Maudhui yamenakiliwa"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Kihariri cha Ubao wa kunakili"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Ubao wa kunakili"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Onyesho la kukagua picha"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"ubadilishe"</string>
<string name="add" msgid="81036585205287996">"Weka"</string>
<string name="manage_users" msgid="1823875311934643849">"Dhibiti watumiaji"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Arifa hii hairuhusu kuburuta kwenye Skrini iliyogawanyika."</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 4423009..f6cab3a 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"வார்த்தைகள் நகலெடுக்கப்பட்டன"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"படம் நகலெடுக்கப்பட்டது"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"உள்ளடக்கம் நகலெடுக்கப்பட்டது"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"கிளிப்போர்டு எடிட்டர்"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"கிளிப்போர்டு"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"படத்தின் மாதிரிக்காட்சி"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"திருத்தும்"</string>
<string name="add" msgid="81036585205287996">"சேர்"</string>
<string name="manage_users" msgid="1823875311934643849">"பயனர்களை நிர்வகித்தல்"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"பிரிக்கப்பட்ட திரைக்குள் இந்த அறிவிப்பை இழுத்துவிட முடியாது."</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index cfdddde..b841ef7 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"కెమెరా"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"ఫోన్"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"వాయిస్ అసిస్టెంట్"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"వాలెట్"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR కోడ్ స్కానర్"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"అన్లాక్ చేయి"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"పరికరం లాక్ చేయబడింది"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"టెక్స్ట్ కాపీ చేయబడింది"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"ఇమేజ్ కాపీ చేయబడింది"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"కంటెంట్ కాపీ చేయబడింది"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"క్లిప్ బోర్డ్ ఎడిటర్"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"క్లిప్ బోర్డ్"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"ఇమేజ్ ప్రివ్యూ"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"ఎడిట్"</string>
<string name="add" msgid="81036585205287996">"జోడించండి"</string>
<string name="manage_users" msgid="1823875311934643849">"యూజర్లను మేనేజ్ చేయండి"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"ఈ నోటిఫికేషన్ స్ప్లిట్స్క్రీన్కు లాగడానికి సపోర్ట్ చేయదు."</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 385ee12..d4efc63 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -372,7 +372,7 @@
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"องค์กรของคุณเป็นเจ้าของอุปกรณ์นี้และอาจตรวจสอบการจราจรของข้อมูลในเครือข่าย"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> เป็นเจ้าของอุปกรณ์นี้และอาจตรวจสอบการจราจรของข้อมูลในเครือข่าย"</string>
<string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"อุปกรณ์นี้ให้บริการโดย <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
- <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"อุปกรณ์นี้เป็นขององค์กรและเชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"อุปกรณ์นี้เป็นขององค์กรและเชื่อมต่ออินเทอร์เน็ตผ่าน <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="quick_settings_disclosure_named_management_named_vpn" msgid="2169227918166358741">"อุปกรณ์นี้เป็นของ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> และเชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
<string name="quick_settings_disclosure_management" msgid="5515296598440684962">"องค์กรของคุณเป็นเจ้าของอุปกรณ์นี้"</string>
<string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> เป็นเจ้าของอุปกรณ์นี้"</string>
@@ -402,8 +402,8 @@
<string name="monitoring_description_management_network_logging" msgid="216983105036994771">"ผู้ดูแลระบบได้เปิดการบันทึกกิจกรรมของเครือข่าย ซึ่งจะตรวจสอบการรับส่งข้อมูลในอุปกรณ์ของคุณ"</string>
<string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"ผู้ดูแลระบบได้เปิดการบันทึกกิจกรรมของเครือข่าย ซึ่งจะตรวจสอบการรับส่งข้อมูลในโปรไฟล์งานแต่ไม่ตรวจสอบในโปรไฟล์ส่วนตัวของคุณ"</string>
<string name="monitoring_description_named_vpn" msgid="7502657784155456414">"อุปกรณ์นี้เชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP">%1$s</xliff:g> ผู้ดูแลระบบไอทีสามารถดูกิจกรรมที่คุณทำในเครือข่ายรวมถึงอีเมลและข้อมูลการท่องเว็บได้"</string>
- <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"อุปกรณ์นี้เชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP_0">%1$s</xliff:g> และ<xliff:g id="VPN_APP_1">%2$s</xliff:g> ผู้ดูแลระบบไอทีสามารถดูกิจกรรมที่คุณทำในเครือข่ายรวมถึงอีเมลและข้อมูลการท่องเว็บได้"</string>
- <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"แอปงานเชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP">%1$s</xliff:g> ผู้ดูแลระบบไอทีและผู้ให้บริการ VPN สามารถดูกิจกรรมที่คุณทำในเครือข่ายในแอปงานได้ ซึ่งรวมถึงอีเมลและข้อมูลการท่องเว็บ"</string>
+ <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"อุปกรณ์นี้เชื่อมต่ออินเทอร์เน็ตผ่าน <xliff:g id="VPN_APP_0">%1$s</xliff:g> และ <xliff:g id="VPN_APP_1">%2$s</xliff:g> ผู้ดูแลระบบไอทีสามารถดูกิจกรรมที่คุณทำในเครือข่าย ซึ่งรวมถึงอีเมลและข้อมูลการท่องเว็บได้"</string>
+ <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"แอปงานเชื่อมต่ออินเทอร์เน็ตผ่าน <xliff:g id="VPN_APP">%1$s</xliff:g> ผู้ดูแลระบบไอทีและผู้ให้บริการ VPN สามารถดูกิจกรรมที่คุณทำในเครือข่ายในแอปงานได้ ซึ่งรวมถึงอีเมลและข้อมูลการท่องเว็บ"</string>
<string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"แอปส่วนตัวเชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP">%1$s</xliff:g> ผู้ให้บริการ VPN สามารถดูกิจกรรมที่คุณทำในเครือข่ายซึ่งรวมถึงอีเมลและข้อมูลการท่องเว็บได้"</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
<string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"เปิดการตั้งค่า VPN"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"คัดลอกข้อความแล้ว"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"คัดลอกรูปภาพแล้ว"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"คัดลอกเนื้อหาแล้ว"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"เครื่องมือแก้ไขคลิปบอร์ด"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"คลิปบอร์ด"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"ตัวอย่างรูปภาพ"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"แก้ไข"</string>
<string name="add" msgid="81036585205287996">"เพิ่ม"</string>
<string name="manage_users" msgid="1823875311934643849">"จัดการผู้ใช้"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"การแจ้งเตือนนี้ไม่รองรับการลากเพื่อแบ่งหน้าจอ"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 6bf3d8f..6ed62f3 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Nakopya ang text"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Nakopya ang larawan"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Nakopya ang content"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Editor ng Clipboard"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Clipboard"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Preview ng larawan"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"i-edit"</string>
<string name="add" msgid="81036585205287996">"Magdagdag"</string>
<string name="manage_users" msgid="1823875311934643849">"Pamahalaan ang mga user"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Hindi sinusuportahan ng notification na ito ang pag-drag sa Splitscreen."</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 9d3c9227..e3182e0 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Metin kopyalandı"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Resim kopyalandı"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"İçerik kopyalandı"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Pano Düzenleyici"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Pano"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Resim önizleme"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"düzenleyin"</string>
<string name="add" msgid="81036585205287996">"Ekle"</string>
<string name="manage_users" msgid="1823875311934643849">"Kullanıcıları yönet"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Bu bildirim, bölünmüş ekrana sürüklenmeyi desteklemiyor."</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 6f36589..53b0909 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -959,14 +959,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Текст скопійовано"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Зображення скопійовано"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Вміст скопійовано"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Редактор буфера обміну"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Буфер обміну"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Попередній перегляд зображення"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"змінити"</string>
<string name="add" msgid="81036585205287996">"Додати"</string>
<string name="manage_users" msgid="1823875311934643849">"Керувати користувачами"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Це сповіщення не підтримує режим розділеного екрана."</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 90b7a2a..8164039 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"کیمرا"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"فون"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"صوتی معاون"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"والٹ"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR کوڈ اسکینر"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"غیر مقفل کریں"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"آلہ مقفل کر دیا گیا"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"ڈیمو موڈ دکھائیں"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"ایتھرنیٹ"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"الارم"</string>
- <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"والٹ"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"اپنے فون سے تیز تر مزید محفوظ خریداریاں کرنے کے لیے، سیٹ اپ مکمل کریں"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"سبھی دکھائیں"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"کھولنے کیلئے تھپتھپائیں"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"متن کاپی ہو گیا"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"تصویر کاپی ہو گئی"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"مواد کاپی ہو گیا"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"کلپ بورڈ ایڈیٹر"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"کلپ بورڈ"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"تصویر کا پیش منظر"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"ترمیم کریں"</string>
<string name="add" msgid="81036585205287996">"شامل کریں"</string>
<string name="manage_users" msgid="1823875311934643849">"صارفین کا نظم کریں"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"یہ اطلاع اسپلٹ اسکرین کو گھسیٹنے کو سپورٹ نہیں کرتا ہے۔"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 7820313..b115cfd 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Matndan nuxsa olindi"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Rasmdan nusxa olindi"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Kontentdan nusxa olindi."</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Vaqtinchalik xotira muharriri"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Vaqtinchalik xotira"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Rasmga razm solish"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"tahrir"</string>
<string name="add" msgid="81036585205287996">"Kiritish"</string>
<string name="manage_users" msgid="1823875311934643849">"Foydalanuvchilarni boshqarish"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Bu bildirishnoma ikkiga ajratilgan ekranda ishlamaydi."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 26f1ec0..976fa40 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"相机"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"电话"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"语音助理"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"电子钱包"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"钱包"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"二维码扫描器"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"解锁"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"设备已锁定"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"显示演示模式"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"以太网"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"闹钟"</string>
- <string name="wallet_title" msgid="5369767670735827105">"电子钱包"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"钱包"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"开始设置,享受更加快捷安全的手机购物体验"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"全部显示"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"点按即可打开"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"文本已复制"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"图片已复制"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"内容已复制"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"剪贴板编辑器"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"剪贴板"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"图片预览"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"修改"</string>
<string name="add" msgid="81036585205287996">"添加"</string>
<string name="manage_users" msgid="1823875311934643849">"管理用户"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"此通知不支持拖动到分屏中。"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index e1b3402..5167093 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"已複製文字"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"已複製圖片"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"已複製內容"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"剪貼簿編輯器"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"剪貼簿"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"圖像預覽"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"編輯"</string>
<string name="add" msgid="81036585205287996">"新增"</string>
<string name="manage_users" msgid="1823875311934643849">"管理使用者"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"此通知無法拖曳到分割螢幕中。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 996cff4..3d47219 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -118,7 +118,7 @@
<string name="accessibility_camera_button" msgid="2938898391716647247">"相機"</string>
<string name="accessibility_phone_button" msgid="4256353121703100427">"電話"</string>
<string name="accessibility_voice_assist_button" msgid="6497706615649754510">"語音小幫手"</string>
- <string name="accessibility_wallet_button" msgid="1458258783460555507">"電子錢包"</string>
+ <string name="accessibility_wallet_button" msgid="1458258783460555507">"錢包"</string>
<string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR 圖碼掃描器"</string>
<string name="accessibility_unlock_button" msgid="122785427241471085">"解除鎖定"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"裝置已鎖定"</string>
@@ -462,7 +462,7 @@
<string name="show_demo_mode" msgid="3677956462273059726">"顯示示範模式"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"乙太網路"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"鬧鐘"</string>
- <string name="wallet_title" msgid="5369767670735827105">"電子錢包"</string>
+ <string name="wallet_title" msgid="5369767670735827105">"錢包"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"完成相關設定之後,就能以更快速安全的方式透過手機消費"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"顯示全部"</string>
<string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"輕觸即可開啟"</string>
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"已複製文字"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"已複製圖片"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"已複製內容"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"剪貼簿編輯器"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"剪貼簿"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"圖片預覽"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"編輯"</string>
<string name="add" msgid="81036585205287996">"新增"</string>
<string name="manage_users" msgid="1823875311934643849">"管理使用者"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"這項通知無法拖曳到分割畫面中。"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 74508bf..3e83354 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -945,14 +945,10 @@
<string name="clipboard_text_copied" msgid="5100836834278976679">"Umbhalo ukopishiwe"</string>
<string name="clipboard_image_copied" msgid="3793365360174328722">"Umfanekiso ukopishiwe"</string>
<string name="clipboard_content_copied" msgid="144452398567828145">"Okuqukethwe kukopishiwe"</string>
- <!-- no translation found for clipboard_editor (2971197550401892843) -->
- <skip />
- <!-- no translation found for clipboard_overlay_window_name (6450043652167357664) -->
- <skip />
- <!-- no translation found for clipboard_image_preview (2156475174343538128) -->
- <skip />
- <!-- no translation found for clipboard_edit (4500155216174011640) -->
- <skip />
+ <string name="clipboard_editor" msgid="2971197550401892843">"Umhleli Webhodi Lokunameka"</string>
+ <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Ibhodi lokunamathisela"</string>
+ <string name="clipboard_image_preview" msgid="2156475174343538128">"Ukubuka kuqala kwesithombe"</string>
+ <string name="clipboard_edit" msgid="4500155216174011640">"hlela"</string>
<string name="add" msgid="81036585205287996">"Faka"</string>
<string name="manage_users" msgid="1823875311934643849">"Phatha abasebenzisi"</string>
<string name="drag_split_not_supported" msgid="4326847447699729722">"Lesi saziso asikusekeli ukuhudulela ku-Splitscreen."</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
index 1142e05..0773347 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
@@ -65,6 +65,12 @@
snapshotId = 0;
}
+ public void recycleBitmap() {
+ if (thumbnail != null) {
+ thumbnail.recycle();
+ }
+ }
+
private static Bitmap makeThumbnail(TaskSnapshot snapshot) {
Bitmap thumbnail = null;
try (final HardwareBuffer buffer = snapshot.getHardwareBuffer()) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
index acd4222..362d7a9 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
@@ -33,7 +33,14 @@
// Main thread callbacks
default void onTaskStackChanged() { }
- default void onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) { }
+
+ /**
+ * @return whether the snapshot is consumed and the lifecycle of the snapshot extends beyond
+ * the lifecycle of this callback.
+ */
+ default boolean onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) {
+ return false;
+ }
default void onActivityPinned(String packageName, int userId, int taskId, int stackId) { }
default void onActivityUnpinned() { }
default void onActivityRestartAttempt(RunningTaskInfo task, boolean homeTaskVisible,
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index 2fd5aae..8af934f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -294,8 +294,17 @@
Trace.beginSection("onTaskSnapshotChanged");
final TaskSnapshot snapshot = (TaskSnapshot) msg.obj;
final ThumbnailData thumbnail = new ThumbnailData(snapshot);
+ boolean snapshotConsumed = false;
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1, thumbnail);
+ boolean consumed = mTaskStackListeners.get(i).onTaskSnapshotChanged(
+ msg.arg1, thumbnail);
+ snapshotConsumed |= consumed;
+ }
+ if (!snapshotConsumed) {
+ thumbnail.recycleBitmap();
+ if (snapshot.getHardwareBuffer() != null) {
+ snapshot.getHardwareBuffer().close();
+ }
}
Trace.endSection();
break;
diff --git a/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt b/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
index 8ab1ab7..34164f3 100644
--- a/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
+++ b/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
@@ -87,20 +87,21 @@
fun onDisplayChanged(displayId: Int) {
val oldMode: Display.Mode? = displayMode
- displayMode = display.mode
+ val display: Display? = context.display
+ displayMode = display?.mode
- if (displayUniqueId != context.display?.uniqueId) {
- displayUniqueId = context.display?.uniqueId
+ if (displayUniqueId != display?.uniqueId) {
+ displayUniqueId = display?.uniqueId
shouldDrawCutout = DisplayCutout.getFillBuiltInDisplayCutout(
context.resources, displayUniqueId)
}
// Skip if display mode or cutout hasn't changed.
if (!displayModeChanged(oldMode, displayMode) &&
- display.cutout == displayInfo.displayCutout) {
+ display?.cutout == displayInfo.displayCutout) {
return
}
- if (displayId == display.displayId) {
+ if (displayId == display?.displayId) {
updateCutout()
updateProtectionBoundingPath()
onUpdate()
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 233f364..6da2f50 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -406,6 +406,15 @@
}
@Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ super.onWindowFocusChanged(hasWindowFocus);
+ if (!hasWindowFocus) {
+ Log.v(TAG, "Lost window focus, dismissing the dialog");
+ animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
+ }
+ }
+
+ @Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -720,7 +729,7 @@
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL,
+ WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL,
windowFlags,
PixelFormat.TRANSLUCENT);
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt
index 2035781..4cd40d2 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt
@@ -15,11 +15,9 @@
*/
package com.android.systemui.biometrics
-import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.phone.SystemUIDialogManager
-import com.android.systemui.statusbar.phone.panelstate.PanelExpansionListener
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager
/**
@@ -30,7 +28,6 @@
statusBarStateController: StatusBarStateController,
panelExpansionStateManager: PanelExpansionStateManager,
systemUIDialogManager: SystemUIDialogManager,
- val broadcastSender: BroadcastSender,
dumpManager: DumpManager
) : UdfpsAnimationViewController<UdfpsBpView>(
view,
@@ -40,29 +37,4 @@
dumpManager
) {
override val tag = "UdfpsBpViewController"
- private val bpPanelExpansionListener = PanelExpansionListener { event ->
- // Notification shade can be expanded but not visible (fraction: 0.0), for example
- // when a heads-up notification (HUN) is showing.
- notificationShadeVisible = event.expanded && event.fraction > 0f
- view.onExpansionChanged(event.fraction)
- cancelAuth()
- }
-
- fun cancelAuth() {
- if (shouldPauseAuth()) {
- broadcastSender.closeSystemDialogs()
- }
- }
-
- override fun onViewAttached() {
- super.onViewAttached()
-
- panelExpansionStateManager.addExpansionListener(bpPanelExpansionListener)
- }
-
- override fun onViewDetached() {
- super.onViewDetached()
-
- panelExpansionStateManager.removeExpansionListener(bpPanelExpansionListener)
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 903b3de..6e2dcae 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -54,7 +54,6 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.biometrics.dagger.BiometricsBackground;
-import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.DozeReceiver;
@@ -128,7 +127,6 @@
@NonNull private final UnlockedScreenOffAnimationController
mUnlockedScreenOffAnimationController;
@NonNull private final LatencyTracker mLatencyTracker;
- @NonNull private final BroadcastSender mBroadcastSender;
@VisibleForTesting @NonNull final BiometricDisplayListener mOrientationListener;
@NonNull private final ActivityLaunchAnimator mActivityLaunchAnimator;
@@ -209,7 +207,7 @@
mUnlockedScreenOffAnimationController, mHalControlsIllumination,
mHbmProvider, requestId, reason, callback,
(view, event, fromUdfpsView) -> onTouch(requestId, event,
- fromUdfpsView), mActivityLaunchAnimator, mBroadcastSender)));
+ fromUdfpsView), mActivityLaunchAnimator)));
}
@Override
@@ -606,7 +604,6 @@
@NonNull LatencyTracker latencyTracker,
@NonNull ActivityLaunchAnimator activityLaunchAnimator,
@NonNull Optional<AlternateUdfpsTouchProvider> aternateTouchProvider,
- @NonNull BroadcastSender broadcastSender,
@BiometricsBackground Executor biometricsExecutor) {
mContext = context;
mExecution = execution;
@@ -637,7 +634,6 @@
mLatencyTracker = latencyTracker;
mActivityLaunchAnimator = activityLaunchAnimator;
mAlternateTouchProvider = aternateTouchProvider.orElse(null);
- mBroadcastSender = broadcastSender;
mBiometricExecutor = biometricsExecutor;
mOrientationListener = new BiometricDisplayListener(
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
index 37db2bd..ec72057 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
@@ -41,7 +41,6 @@
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.R
import com.android.systemui.animation.ActivityLaunchAnimator
-import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.LockscreenShadeTransitionController
@@ -84,8 +83,7 @@
@ShowReason val requestReason: Int,
private val controllerCallback: IUdfpsOverlayControllerCallback,
private val onTouch: (View, MotionEvent, Boolean) -> Boolean,
- private val activityLaunchAnimator: ActivityLaunchAnimator,
- private val broadcastSender: BroadcastSender
+ private val activityLaunchAnimator: ActivityLaunchAnimator
) {
/** The view, when [isShowing], or null. */
var overlayView: UdfpsView? = null
@@ -104,8 +102,8 @@
fitInsetsTypes = 0
gravity = android.view.Gravity.TOP or android.view.Gravity.LEFT
layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
- flags = (Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS
- or WindowManager.LayoutParams.FLAG_SPLIT_TOUCH)
+ flags =
+ (Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS or WindowManager.LayoutParams.FLAG_SPLIT_TOUCH)
privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
// Avoid announcing window title.
accessibilityTitle = " "
@@ -227,7 +225,6 @@
statusBarStateController,
panelExpansionStateManager,
dialogManager,
- broadcastSender,
dumpManager
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index d634030..c686b48 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -216,13 +216,6 @@
*/
override fun setLauncherUnlockController(callback: ILauncherUnlockAnimationController?) {
launcherUnlockController = callback
-
- // If the provided callback dies, set it to null. We'll always check whether it's null
- // to avoid DeadObjectExceptions.
- callback?.asBinder()?.linkToDeath({
- launcherUnlockController = null
- launcherSmartspaceState = null
- }, 0 /* flags */)
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 80ad93f..3ad43ac 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -485,6 +485,8 @@
*/
private IRemoteAnimationRunner mKeyguardExitAnimationRunner;
+ private CentralSurfaces mCentralSurfaces;
+
private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
new DeviceConfig.OnPropertiesChangedListener() {
@Override
@@ -845,6 +847,13 @@
+ mOccluded);
}
+ @Override
+ public void onLaunchAnimationEnd(boolean launchIsFullScreen) {
+ if (launchIsFullScreen) {
+ mCentralSurfaces.instantCollapseNotificationPanel();
+ }
+ }
+
@NonNull
@Override
public ViewGroup getLaunchContainer() {
@@ -2846,6 +2855,7 @@
@Nullable PanelExpansionStateManager panelExpansionStateManager,
BiometricUnlockController biometricUnlockController,
View notificationContainer, KeyguardBypassController bypassController) {
+ mCentralSurfaces = centralSurfaces;
mKeyguardViewControllerLazy.get().registerCentralSurfaces(
centralSurfaces,
panelView,
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index dea1325..33453a4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -677,6 +677,7 @@
scaleTransitionDrawableLayer(transitionDrawable, 1, width, height);
transitionDrawable.setLayerGravity(0, Gravity.CENTER);
transitionDrawable.setLayerGravity(1, Gravity.CENTER);
+ transitionDrawable.setCrossFadeEnabled(!isArtworkBound);
albumView.setImageDrawable(transitionDrawable);
transitionDrawable.startTransition(isArtworkBound ? 333 : 80);
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
index 360f865..aeeef6b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
@@ -216,4 +216,20 @@
/** Unique id for this device */
val id: String? = null
-)
+) {
+ /**
+ * Check whether [MediaDeviceData] objects are equal in all fields except the icon. The icon
+ * is ignored because it can change by reference frequently depending on the device type's
+ * implementation, but this is not usually relevant unless other info has changed
+ */
+ fun equalsWithoutIcon(other: MediaDeviceData?): Boolean {
+ if (other == null) {
+ return false
+ }
+
+ return enabled == other.enabled &&
+ name == other.name &&
+ intent == other.intent &&
+ id == other.id
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
index 8558859..baed1c4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
@@ -155,8 +155,8 @@
private var playbackType = PLAYBACK_TYPE_UNKNOWN
private var current: MediaDeviceData? = null
set(value) {
- val hasSameId = value?.id != null && value.id == field?.id
- if (!started || (!hasSameId && value != field)) {
+ val sameWithoutIcon = value != null && value.equalsWithoutIcon(field)
+ if (!started || !sameWithoutIcon) {
field = value
fgExecutor.execute {
processDevice(key, oldKey, value)
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index 24dfeaf..f0ce30d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -107,6 +107,7 @@
@Override
void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin, int position) {
super.onBind(device, topMargin, bottomMargin, position);
+ boolean isMutingExpectedDeviceExist = mController.hasMutingExpectedDevice();
final boolean currentlyConnected = !mIncludeDynamicGroup
&& isCurrentlyConnected(device);
boolean isCurrentSeekbarInvisible = mSeekBar.getVisibility() == View.GONE;
@@ -146,7 +147,19 @@
}
} else {
// Set different layout for each device
- if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
+ if (device.isMutingExpectedDevice()
+ && !mController.isCurrentConnectedDeviceRemote()) {
+ mTitleIcon.setImageDrawable(
+ mContext.getDrawable(R.drawable.media_output_icon_volume));
+ mTitleIcon.setColorFilter(mController.getColorItemContent());
+ mTitleText.setTextColor(mController.getColorItemContent());
+ setSingleLineLayout(getItemTitle(device), true /* bFocused */,
+ false /* showSeekBar */,
+ false /* showProgressBar */, false /* showStatus */);
+ initMutingExpectedDevice();
+ mCurrentActivePosition = position;
+ mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
+ } else if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
setUpDeviceIcon(device);
mStatusIcon.setImageDrawable(
mContext.getDrawable(R.drawable.media_output_status_failed));
@@ -193,17 +206,26 @@
mEndTouchArea.setImportantForAccessibility(
View.IMPORTANT_FOR_ACCESSIBILITY_YES);
setUpContentDescriptionForView(mEndTouchArea, true, device);
- } else if (!mController.hasAdjustVolumeUserRestriction() && currentlyConnected) {
- mTitleIcon.setImageDrawable(
- mContext.getDrawable(R.drawable.media_output_icon_volume));
- mTitleIcon.setColorFilter(mController.getColorItemContent());
- mTitleText.setTextColor(mController.getColorItemContent());
- setSingleLineLayout(getItemTitle(device), true /* bFocused */,
- true /* showSeekBar */,
- false /* showProgressBar */, false /* showStatus */);
- initSeekbar(device, isCurrentSeekbarInvisible);
- setUpContentDescriptionForView(mContainerLayout, false, device);
- mCurrentActivePosition = position;
+ } else if (!mController.hasAdjustVolumeUserRestriction()
+ && currentlyConnected) {
+ if (isMutingExpectedDeviceExist
+ && !mController.isCurrentConnectedDeviceRemote()) {
+ // mark as disconnected and set special click listener
+ setUpDeviceIcon(device);
+ setSingleLineLayout(getItemTitle(device), false /* bFocused */);
+ mContainerLayout.setOnClickListener(v -> cancelMuteAwaitConnection());
+ } else {
+ mTitleIcon.setImageDrawable(
+ mContext.getDrawable(R.drawable.media_output_icon_volume));
+ mTitleIcon.setColorFilter(mController.getColorItemContent());
+ mTitleText.setTextColor(mController.getColorItemContent());
+ setSingleLineLayout(getItemTitle(device), true /* bFocused */,
+ true /* showSeekBar */,
+ false /* showProgressBar */, false /* showStatus */);
+ initSeekbar(device, isCurrentSeekbarInvisible);
+ setUpContentDescriptionForView(mContainerLayout, false, device);
+ mCurrentActivePosition = position;
+ }
} else if (isDeviceIncluded(mController.getSelectableMediaDevice(), device)) {
setUpDeviceIcon(device);
mCheckBox.setOnCheckedChangeListener(null);
@@ -269,6 +291,11 @@
notifyDataSetChanged();
}
+ private void cancelMuteAwaitConnection() {
+ mController.cancelMuteAwaitConnection();
+ notifyDataSetChanged();
+ }
+
private void setUpContentDescriptionForView(View view, boolean clickable,
MediaDevice device) {
view.setClickable(clickable);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index b407e76f..ccc0a3d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -309,6 +309,17 @@
});
}
+ void initMutingExpectedDevice() {
+ disableSeekBar();
+ final Drawable backgroundDrawable = mContext.getDrawable(
+ R.drawable.media_output_item_background_active)
+ .mutate();
+ backgroundDrawable.setColorFilter(
+ new PorterDuffColorFilter(mController.getColorConnectedItemBackground(),
+ PorterDuff.Mode.SRC_IN));
+ mItemLayout.setBackground(backgroundDrawable);
+ }
+
void initSessionSeekbar() {
disableSeekBar();
mSeekBar.setMax(mController.getSessionVolumeMax());
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt
index 31266b6..38005db 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt
@@ -17,6 +17,7 @@
package com.android.systemui.media.dialog
import android.content.Context
+import android.media.AudioManager
import android.media.session.MediaSessionManager
import android.view.View
import com.android.internal.logging.UiEventLogger
@@ -41,7 +42,8 @@
private val notifCollection: CommonNotifCollection,
private val uiEventLogger: UiEventLogger,
private val dialogLaunchAnimator: DialogLaunchAnimator,
- private val nearbyMediaDevicesManagerOptional: Optional<NearbyMediaDevicesManager>
+ private val nearbyMediaDevicesManagerOptional: Optional<NearbyMediaDevicesManager>,
+ private val audioManager: AudioManager
) {
var mediaOutputBroadcastDialog: MediaOutputBroadcastDialog? = null
@@ -52,7 +54,7 @@
val controller = MediaOutputController(context, packageName,
mediaSessionManager, lbm, starter, notifCollection,
- dialogLaunchAnimator, nearbyMediaDevicesManagerOptional)
+ dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager)
val dialog =
MediaOutputBroadcastDialog(context, aboveStatusBar, broadcastSender, controller)
mediaOutputBroadcastDialog = dialog
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index 9329b1b..42e9af8 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -34,6 +34,7 @@
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
+import android.media.AudioManager;
import android.media.INearbyMediaDevicesUpdateCallback;
import android.media.MediaMetadata;
import android.media.MediaRoute2Info;
@@ -112,6 +113,7 @@
@VisibleForTesting
final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
final List<MediaDevice> mCachedMediaDevices = new CopyOnWriteArrayList<>();
+ private final AudioManager mAudioManager;
private final NearbyMediaDevicesManager mNearbyMediaDevicesManager;
private final Map<String, Integer> mNearbyDeviceInfoMap = new ConcurrentHashMap<>();
@@ -122,7 +124,6 @@
Callback mCallback;
@VisibleForTesting
LocalMediaManager mLocalMediaManager;
-
private MediaOutputMetricLogger mMetricLogger;
private int mColorItemContent;
@@ -145,13 +146,15 @@
lbm, ActivityStarter starter,
CommonNotifCollection notifCollection,
DialogLaunchAnimator dialogLaunchAnimator,
- Optional<NearbyMediaDevicesManager> nearbyMediaDevicesManagerOptional) {
+ Optional<NearbyMediaDevicesManager> nearbyMediaDevicesManagerOptional,
+ AudioManager audioManager) {
mContext = context;
mPackageName = packageName;
mMediaSessionManager = mediaSessionManager;
mLocalBluetoothManager = lbm;
mActivityStarter = starter;
mNotifCollection = notifCollection;
+ mAudioManager = audioManager;
InfoMediaManager imm = new InfoMediaManager(mContext, packageName, null, lbm);
mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName);
mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName);
@@ -217,14 +220,14 @@
return false;
}
- void setRefreshing(boolean refreshing) {
- mIsRefreshing = refreshing;
- }
-
boolean isRefreshing() {
return mIsRefreshing;
}
+ void setRefreshing(boolean refreshing) {
+ mIsRefreshing = refreshing;
+ }
+
void stop() {
if (mMediaController != null) {
mMediaController.unregisterCallback(mCb);
@@ -275,6 +278,27 @@
mMetricLogger.logOutputFailure(new ArrayList<>(mMediaDevices), reason);
}
+ /**
+ * Checks if there's any muting expected device exist
+ */
+ public boolean hasMutingExpectedDevice() {
+ return mAudioManager.getMutingExpectedDevice() != null;
+ }
+
+ /**
+ * Cancels mute await connection action in follow up request
+ */
+ public void cancelMuteAwaitConnection() {
+ if (mAudioManager.getMutingExpectedDevice() == null) {
+ return;
+ }
+ try {
+ mAudioManager.cancelMuteAwaitConnection(mAudioManager.getMutingExpectedDevice());
+ } catch (Exception e) {
+ Log.d(TAG, "Unable to cancel mute await connection");
+ }
+ }
+
Drawable getAppSourceIcon() {
if (mPackageName.isEmpty()) {
return null;
@@ -471,12 +495,26 @@
// For the first time building list, to make sure the top device is the connected
// device.
if (mMediaDevices.isEmpty()) {
- final MediaDevice connectedMediaDevice = getCurrentConnectedMediaDevice();
+ boolean needToHandleMutingExpectedDevice =
+ hasMutingExpectedDevice() && !isCurrentConnectedDeviceRemote();
+ final MediaDevice connectedMediaDevice =
+ needToHandleMutingExpectedDevice ? null
+ : getCurrentConnectedMediaDevice();
if (connectedMediaDevice == null) {
if (DEBUG) {
- Log.d(TAG, "No connected media device.");
+ Log.d(TAG, "No connected media device or muting expected device exist.");
}
- mMediaDevices.addAll(devices);
+ if (needToHandleMutingExpectedDevice) {
+ for (MediaDevice device : devices) {
+ if (device.isMutingExpectedDevice()) {
+ mMediaDevices.add(0, device);
+ } else {
+ mMediaDevices.add(device);
+ }
+ }
+ } else {
+ mMediaDevices.addAll(devices);
+ }
return;
}
for (MediaDevice device : devices) {
@@ -516,6 +554,12 @@
}
+ boolean isCurrentConnectedDeviceRemote() {
+ MediaDevice currentConnectedMediaDevice = getCurrentConnectedMediaDevice();
+ return currentConnectedMediaDevice != null && isActiveRemoteDevice(
+ currentConnectedMediaDevice);
+ }
+
List<MediaDevice> getGroupMediaDevices() {
final List<MediaDevice> selectedDevices = getSelectedMediaDevice();
final List<MediaDevice> selectableDevices = getSelectableMediaDevice();
@@ -731,7 +775,8 @@
void launchMediaOutputBroadcastDialog(View mediaOutputDialog, BroadcastSender broadcastSender) {
MediaOutputController controller = new MediaOutputController(mContext, mPackageName,
mMediaSessionManager, mLocalBluetoothManager, mActivityStarter,
- mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager));
+ mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager),
+ mAudioManager);
MediaOutputBroadcastDialog dialog = new MediaOutputBroadcastDialog(mContext, true,
broadcastSender, controller);
mDialogLaunchAnimator.showFromView(dialog, mediaOutputDialog);
@@ -887,8 +932,9 @@
}
boolean isVolumeControlEnabled(@NonNull MediaDevice device) {
- return isPlayBackInfoLocal()
- || device.getDeviceType() != MediaDevice.MediaDeviceType.TYPE_CAST_GROUP_DEVICE;
+ return (isPlayBackInfoLocal()
+ || device.getDeviceType() != MediaDevice.MediaDeviceType.TYPE_CAST_GROUP_DEVICE)
+ && !device.isVolumeFixed();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
index 0d7d60a..36a46f0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
@@ -17,6 +17,7 @@
package com.android.systemui.media.dialog
import android.content.Context
+import android.media.AudioManager
import android.media.session.MediaSessionManager
import android.view.View
import com.android.internal.logging.UiEventLogger
@@ -41,7 +42,8 @@
private val notifCollection: CommonNotifCollection,
private val uiEventLogger: UiEventLogger,
private val dialogLaunchAnimator: DialogLaunchAnimator,
- private val nearbyMediaDevicesManagerOptional: Optional<NearbyMediaDevicesManager>
+ private val nearbyMediaDevicesManagerOptional: Optional<NearbyMediaDevicesManager>,
+ private val audioManager: AudioManager
) {
companion object {
var mediaOutputDialog: MediaOutputDialog? = null
@@ -54,7 +56,7 @@
val controller = MediaOutputController(context, packageName,
mediaSessionManager, lbm, starter, notifCollection,
- dialogLaunchAnimator, nearbyMediaDevicesManagerOptional)
+ dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager)
val dialog =
MediaOutputDialog(context, aboveStatusBar, broadcastSender, controller, uiEventLogger)
mediaOutputDialog = dialog
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 9de132f..41724ef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -151,15 +151,17 @@
mHorizontalContentContainer.setClipChildren(true);
mHorizontalContentContainer.setClipToPadding(false);
// Don't clip on the top, that way, secondary pages tiles can animate up
+ // Clipping coordinates should be relative to this view, not absolute (parent coordinates)
mHorizontalContentContainer.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
- if (left != oldLeft || right != oldRight || bottom != oldBottom) {
- mClippingRect.left = left;
- mClippingRect.right = right;
- mClippingRect.bottom = bottom;
+ if ((right - left) != (oldRight - oldLeft)
+ || ((bottom - top) != (oldBottom - oldTop))) {
+ mClippingRect.right = right - left;
+ mClippingRect.bottom = bottom - top;
mHorizontalContentContainer.setClipBounds(mClippingRect);
}
});
+ mClippingRect.left = 0;
mClippingRect.top = -1000;
mHorizontalContentContainer.setClipBounds(mClippingRect);
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 8ce422a..5b6e5ce 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -83,6 +83,8 @@
import android.widget.Toast;
import android.window.WindowContext;
+import androidx.concurrent.futures.CallbackToFutureAdapter;
+
import com.android.internal.app.ChooserActivity;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.policy.PhoneWindow;
@@ -254,7 +256,7 @@
private final WindowManager mWindowManager;
private final WindowManager.LayoutParams mWindowLayoutParams;
private final AccessibilityManager mAccessibilityManager;
- private final MediaPlayer mCameraSound;
+ private final ListenableFuture<MediaPlayer> mCameraSound;
private final ScrollCaptureClient mScrollCaptureClient;
private final PhoneWindow mWindow;
private final DisplayManager mDisplayManager;
@@ -338,13 +340,7 @@
reloadAssets();
// Setup the Camera shutter sound
- mCameraSound = MediaPlayer.create(mContext,
- Uri.fromFile(new File(mContext.getResources().getString(
- com.android.internal.R.string.config_cameraShutterSound))), null,
- new AudioAttributes.Builder()
- .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
- .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
- .build(), AudioSystem.newAudioSessionId());
+ mCameraSound = loadCameraSound();
mCopyBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -442,16 +438,32 @@
return mScreenshotView.isPendingSharedTransition();
}
+ // Any cleanup needed when the service is being destroyed.
+ void onDestroy() {
+ removeWindow();
+ releaseMediaPlayer();
+ releaseContext();
+ mBgExecutor.shutdownNow();
+ }
+
/**
* Release the constructed window context.
*/
- void releaseContext() {
+ private void releaseContext() {
mContext.unregisterReceiver(mCopyBroadcastReceiver);
mContext.release();
- if (mCameraSound != null) {
- mCameraSound.release();
+ }
+
+ private void releaseMediaPlayer() {
+ // Note that this may block if the sound is still being loaded (very unlikely) but we can't
+ // reliably release in the background because the service is being destroyed.
+ try {
+ MediaPlayer player = mCameraSound.get();
+ if (player != null) {
+ player.release();
+ }
+ } catch (InterruptedException | ExecutionException e) {
}
- mBgExecutor.shutdownNow();
}
/**
@@ -822,15 +834,42 @@
}
}
+ private ListenableFuture<MediaPlayer> loadCameraSound() {
+ // The media player creation is slow and needs on the background thread.
+ return CallbackToFutureAdapter.getFuture((completer) -> {
+ mBgExecutor.execute(() -> {
+ MediaPlayer player = MediaPlayer.create(mContext,
+ Uri.fromFile(new File(mContext.getResources().getString(
+ com.android.internal.R.string.config_cameraShutterSound))), null,
+ new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+ .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ .build(), AudioSystem.newAudioSessionId());
+ completer.set(player);
+ });
+ return "ScreenshotController#loadCameraSound";
+ });
+ }
+
+ private void playCameraSound() {
+ mCameraSound.addListener(() -> {
+ try {
+ MediaPlayer player = mCameraSound.get();
+ if (player != null) {
+ player.start();
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ }
+ }, mBgExecutor);
+ }
+
/**
* Save the bitmap but don't show the normal screenshot UI.. just a toast (or notification on
* failure).
*/
private void saveScreenshotAndToast(Consumer<Uri> finisher) {
// Play the shutter sound to notify that we've taken a screenshot
- if (mCameraSound != null) {
- mCameraSound.start();
- }
+ playCameraSound();
saveScreenshotInWorkerThread(
/* onComplete */ finisher,
@@ -864,9 +903,7 @@
mScreenshotView.createScreenshotDropInAnimation(screenRect, showFlash);
// Play the shutter sound to notify that we've taken a screenshot
- if (mCameraSound != null) {
- mCameraSound.start();
- }
+ playCameraSound();
if (DEBUG_ANIM) {
Log.d(TAG, "starting post-screenshot animation");
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index 90e7631..32d8203 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -153,8 +153,7 @@
public void onDestroy() {
super.onDestroy();
if (mScreenshot != null) {
- mScreenshot.removeWindow();
- mScreenshot.releaseContext();
+ mScreenshot.onDestroy();
mScreenshot = null;
}
if (DEBUG_SERVICE) {
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
index c7a8fa2..5e908d9 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
@@ -46,6 +46,8 @@
/**
* List of profiles associated with the current user.
+ *
+ * Quiet work profiles will still appear here, but will have the `QUIET_MODE` flag.
*/
val userProfiles: List<UserInfo>
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index 80d5f16..47bed46 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -108,8 +108,12 @@
val filter = IntentFilter().apply {
addAction(Intent.ACTION_USER_SWITCHED)
+ // These get called when a managed profile goes in or out of quiet mode.
addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE)
+ addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)
+
addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED)
+ addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED)
}
context.registerReceiverForAllUsers(this, filter, null /* permission */, backgroundHandler)
@@ -121,7 +125,10 @@
Intent.ACTION_USER_SWITCHED -> {
handleSwitchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL))
}
- Intent.ACTION_MANAGED_PROFILE_AVAILABLE, Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE -> {
+ Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
+ Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
+ Intent.ACTION_MANAGED_PROFILE_REMOVED,
+ Intent.ACTION_MANAGED_PROFILE_UNLOCKED -> {
handleProfilesChanged()
}
}
@@ -208,7 +215,7 @@
pw.println("Initialized: $initialized")
if (initialized) {
pw.println("userId: $userId")
- val ids = userProfiles.map { it.id }
+ val ids = userProfiles.map { it.toFullString() }
pw.println("userProfiles: $ids")
}
val list = synchronized(callbacks) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index a8d6852..126a986 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -265,12 +265,12 @@
}
override fun onStateChanged(newState: Int) {
- if (screenOffAnimationController.overrideNotificationsFullyDozingOnKeyguard() &&
- state == StatusBarState.KEYGUARD &&
- newState == StatusBarState.SHADE) {
- // If we're animating the screen off and going from KEYGUARD back to SHADE, the
- // animation was cancelled and we are unlocking. Override the doze amount to 0f (not
- // dozing) so that the notifications are no longer hidden.
+ if (state == StatusBarState.SHADE && newState == StatusBarState.SHADE) {
+ // The SHADE -> SHADE transition is only possible as part of cancelling the screen-off
+ // animation (e.g. by fingerprint unlock). This is done because the system is in an
+ // undefined state, so it's an indication that we should do state cleanup. We override
+ // the doze amount to 0f (not dozing) so that the notifications are no longer hidden.
+ // See: UnlockedScreenOffAnimationController.onFinishedWakingUp()
setDozeAmount(0f, 0f)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 4fc347a..aedbd1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -158,13 +158,6 @@
private long initializationTime = -1;
/**
- * Whether or not this row represents a system notification. Note that if this is
- * {@code null}, that means we were either unable to retrieve the info or have yet to
- * retrieve the info.
- */
- public Boolean mIsSystemNotification;
-
- /**
* Has the user sent a reply through this Notification.
*/
private boolean hasSentReply;
@@ -777,12 +770,28 @@
if (mSbn.getNotification().isMediaNotification()) {
return true;
}
- if (mIsSystemNotification != null && mIsSystemNotification) {
+ if (!isBlockable()) {
return true;
}
return false;
}
+ /**
+ * Returns whether this row is considered blockable (i.e. it's not a system notif
+ * or is not in an allowList).
+ */
+ public boolean isBlockable() {
+ if (getChannel() == null) {
+ return false;
+ }
+ if (getChannel().isImportanceLockedByCriticalDeviceFunction()
+ && !getChannel().isBlockable()) {
+ return false;
+ }
+
+ return true;
+ }
+
private boolean shouldSuppressVisualEffect(int effect) {
if (isExemptFromDndVisualSuppression()) {
return false;
@@ -858,15 +867,6 @@
}
/**
- * Whether or not this row represents a system notification. Note that if this is
- * {@code null}, that means we were either unable to retrieve the info or have yet to
- * retrieve the info.
- */
- public Boolean isSystemNotification() {
- return mIsSystemNotification;
- }
-
- /**
* Set this notification to be sensitive.
*
* @param sensitive true if the content of this notification is sensitive right now
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
index aac5b8d..ff1c70c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
@@ -41,6 +41,7 @@
private final HighPriorityProvider mHighPriorityProvider;
private final SectionHeaderVisibilityProvider mSectionHeaderVisibilityProvider;
private final KeyguardNotificationVisibilityProvider mKeyguardNotificationVisibilityProvider;
+ private final SharedCoordinatorLogger mLogger;
@Inject
public KeyguardCoordinator(
@@ -48,12 +49,14 @@
KeyguardUpdateMonitor keyguardUpdateMonitor,
HighPriorityProvider highPriorityProvider,
SectionHeaderVisibilityProvider sectionHeaderVisibilityProvider,
- KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider) {
+ KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider,
+ SharedCoordinatorLogger logger) {
mStatusBarStateController = statusBarStateController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mHighPriorityProvider = highPriorityProvider;
mSectionHeaderVisibilityProvider = sectionHeaderVisibilityProvider;
mKeyguardNotificationVisibilityProvider = keyguardNotificationVisibilityProvider;
+ mLogger = logger;
}
@Override
@@ -81,6 +84,7 @@
}
private void invalidateListFromFilter(String reason) {
+ mLogger.logKeyguardCoordinatorInvalidated(reason);
updateSectionHeadersVisibility();
mNotifFilter.invalidateList();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SharedCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SharedCoordinatorLogger.kt
index c85fc1e..25bc641 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SharedCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SharedCoordinatorLogger.kt
@@ -35,4 +35,12 @@
"Current user or profiles changed. Current user is $int1; profiles are $str1"
})
}
+
+ fun logKeyguardCoordinatorInvalidated(reason: String) {
+ buffer.log("KeyguardCoordinator", LogLevel.DEBUG, {
+ str1 = reason
+ }, {
+ "KeyguardCoordinator invalidated: $str1"
+ })
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt
index a0c39c6..fd5bae1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt
@@ -16,15 +16,13 @@
package com.android.systemui.statusbar.notification.collection.provider
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.content.IntentFilter
import android.os.Build
import android.util.Log
import com.android.systemui.Dumpable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.commandline.Command
+import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.util.Assert
import com.android.systemui.util.ListenerSet
@@ -39,20 +37,19 @@
* The only configuration is a list of allowed packages. When this list is empty, the feature is
* disabled. When SystemUI starts up, this feature is disabled.
*
- * To enabled filtering, provide the list of packages in a comma-separated list using the command:
+ * To enabled filtering, provide the space-separated list of packages using the command:
*
- * `$ adb shell am broadcast -a com.android.systemui.action.SET_NOTIF_DEBUG_MODE
- * --esal allowed_packages <comma-separated-packages>`
+ * `$ adb shell cmd statusbar notif-filter allowed-pkgs <package> ...`
*
- * To disable filtering, send the action without a list:
+ * To disable filtering, send the command without any packages, or explicitly reset:
*
- * `$ adb shell am broadcast -a com.android.systemui.action.SET_NOTIF_DEBUG_MODE`
+ * `$ adb shell cmd statusbar notif-filter reset`
*
* NOTE: this feature only works on debug builds, and when the broadcaster is root.
*/
@SysUISingleton
class DebugModeFilterProvider @Inject constructor(
- private val context: Context,
+ private val commandRegistry: CommandRegistry,
dumpManager: DumpManager
) : Dumpable {
private var allowedPackages: List<String> = emptyList()
@@ -74,10 +71,8 @@
val needsInitialization = listeners.isEmpty()
listeners.addIfAbsent(listener)
if (needsInitialization) {
- val filter = IntentFilter().apply { addAction(ACTION_SET_NOTIF_DEBUG_MODE) }
- val permission = NOTIF_DEBUG_MODE_PERMISSION
- context.registerReceiver(mReceiver, filter, permission, null, Context.RECEIVER_EXPORTED)
- Log.d(TAG, "Registered: $mReceiver")
+ commandRegistry.registerCommand("notif-filter") { NotifFilterCommand() }
+ Log.d(TAG, "Registered notif-filter command")
}
}
@@ -100,30 +95,49 @@
}
}
- private val mReceiver: BroadcastReceiver = object : BroadcastReceiver() {
- override fun onReceive(context: Context, intent: Intent?) {
- val action = intent?.action
- if (ACTION_SET_NOTIF_DEBUG_MODE == action) {
- // TODO(b/235268992) remove
- Log.d(TAG, "ACTION_SET_NOTIF_DEBUG_MODE enter")
- allowedPackages = intent.extras?.getStringArrayList(EXTRA_ALLOWED_PACKAGES)
- ?: emptyList()
- Log.d(TAG, "Updated allowedPackages: $allowedPackages")
- listeners.forEach(Runnable::run)
- // TODO(b/235268992) remove
- Log.d(TAG, "ACTION_SET_NOTIF_DEBUG_MODE leave")
- } else {
- Log.d(TAG, "Malformed intent: $intent")
- }
- }
- }
-
companion object {
private const val TAG = "DebugModeFilterProvider"
- private const val ACTION_SET_NOTIF_DEBUG_MODE =
- "com.android.systemui.action.SET_NOTIF_DEBUG_MODE"
- private const val NOTIF_DEBUG_MODE_PERMISSION =
- "com.android.systemui.permission.NOTIF_DEBUG_MODE"
- private const val EXTRA_ALLOWED_PACKAGES = "allowed_packages"
+ }
+
+ inner class NotifFilterCommand : Command {
+ override fun execute(pw: PrintWriter, args: List<String>) {
+ when (args.firstOrNull()) {
+ "reset" -> {
+ if (args.size > 1) {
+ return invalidCommand(pw, "Unexpected arguments for 'reset' command")
+ }
+ allowedPackages = emptyList()
+ }
+ "allowed-pkgs" -> {
+ allowedPackages = args.drop(1)
+ }
+ null -> return invalidCommand(pw, "Missing command")
+ else -> return invalidCommand(pw, "Unknown command: ${args.firstOrNull()}")
+ }
+ Log.d(TAG, "Updated allowedPackages: $allowedPackages")
+ if (allowedPackages.isEmpty()) {
+ pw.print("Resetting allowedPackages ... ")
+ } else {
+ pw.print("Updating allowedPackages: $allowedPackages ... ")
+ }
+ listeners.forEach(Runnable::run)
+ pw.println("DONE")
+ }
+
+ private fun invalidCommand(pw: PrintWriter, reason: String) {
+ pw.println("Error: $reason")
+ pw.println()
+ help(pw)
+ }
+
+ override fun help(pw: PrintWriter) {
+ pw.println("Usage: adb shell cmd statusbar notif-filter <command>")
+ pw.println("Available commands:")
+ pw.println(" reset")
+ pw.println(" Restore the default system behavior.")
+ pw.println(" allowed-pkgs <package> ...")
+ pw.println(" Hide all notification except from packages listed here.")
+ pw.println(" Providing no packages is treated as a reset.")
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
index 6cd3a6a..0b6b929 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
@@ -25,12 +25,15 @@
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.ListenerSet
+import com.android.systemui.util.asIndenting
import com.android.systemui.util.settings.GlobalSettings
import com.android.systemui.util.settings.SecureSettings
+import com.android.systemui.util.withIncreasedIndent
import dagger.Binds
import dagger.Module
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
+import java.io.PrintWriter
import java.util.function.Consumer
import javax.inject.Inject
@@ -209,6 +212,16 @@
}
}
+ override fun dump(pw: PrintWriter, args: Array<out String>) = pw.asIndenting().run {
+ println("isLockedOrLocking=$isLockedOrLocking")
+ withIncreasedIndent {
+ println("keyguardStateController.isShowing=${keyguardStateController.isShowing}")
+ println("statusBarStateController.currentOrUpcomingState=" +
+ "${statusBarStateController.currentOrUpcomingState}")
+ }
+ println("hideSilentNotificationsOnLockscreen=$hideSilentNotificationsOnLockscreen")
+ }
+
private val isLockedOrLocking get() =
keyguardStateController.isShowing ||
statusBarStateController.currentOrUpcomingState == StatusBarState.KEYGUARD
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 7c206eb..eb496ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -513,16 +513,10 @@
* or is in an allowList).
*/
public boolean getIsNonblockable() {
- if (mEntry == null || mEntry.getChannel() == null) {
- Log.w(TAG, "missing entry or channel");
+ if (mEntry == null) {
return true;
}
- if (mEntry.getChannel().isImportanceLockedByCriticalDeviceFunction()
- && !mEntry.getChannel().isBlockable()) {
- return true;
- }
-
- return false;
+ return !mEntry.isBlockable();
}
private boolean isConversation() {
@@ -1669,6 +1663,11 @@
}
}
+ @VisibleForTesting
+ protected void setEntry(NotificationEntry entry) {
+ mEntry = entry;
+ }
+
private final Runnable mExpireRecentlyAlertedFlag = () -> applyAudiblyAlertedRecently(false);
private void applyAudiblyAlertedRecently(boolean audiblyAlertedRecently) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 367684f..705de9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -1596,7 +1596,7 @@
}
}
});
- mStatusBarKeyguardViewManager.registerCentralSurfaces(
+ mKeyguardViewMediator.registerCentralSurfaces(
/* statusBar= */ this,
mNotificationPanelViewController,
mPanelExpansionStateManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index ba1088f..557c995 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -958,14 +958,16 @@
});
}
- private void onFinishInflate() {
+ @VisibleForTesting
+ void onFinishInflate() {
loadDimens();
mKeyguardStatusBar = mView.findViewById(R.id.keyguard_header);
FrameLayout userAvatarContainer = null;
KeyguardUserSwitcherView keyguardUserSwitcherView = null;
- if (mKeyguardUserSwitcherEnabled && mUserManager.isUserSwitcherEnabled()) {
+ if (mKeyguardUserSwitcherEnabled && mUserManager.isUserSwitcherEnabled(
+ mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))) {
if (mKeyguardQsUserSwitchEnabled) {
ViewStub stub = mView.findViewById(R.id.keyguard_qs_user_switch_stub);
userAvatarContainer = (FrameLayout) stub.inflate();
@@ -1191,7 +1193,8 @@
return view;
}
- private void reInflateViews() {
+ @VisibleForTesting
+ void reInflateViews() {
if (DEBUG_LOGCAT) Log.d(TAG, "reInflateViews");
// Re-inflate the status view group.
KeyguardStatusView keyguardStatusView =
@@ -1212,7 +1215,8 @@
// Re-inflate the keyguard user switcher group.
updateUserSwitcherFlags();
- boolean isUserSwitcherEnabled = mUserManager.isUserSwitcherEnabled();
+ boolean isUserSwitcherEnabled = mUserManager.isUserSwitcherEnabled(
+ mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user));
boolean showQsUserSwitch = mKeyguardQsUserSwitchEnabled && isUserSwitcherEnabled;
boolean showKeyguardUserSwitcher =
!mKeyguardQsUserSwitchEnabled
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt
index 1206d05..ebedbf9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt
@@ -200,6 +200,7 @@
containerPadding = bottomStableInsets
} else {
containerPadding = 0
+ stackScrollMargin = bottomStableInsets + notificationsBottomMargin
}
}
val qsContainerPadding = if (!(isQSCustomizing || isQSDetailShowing)) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
index 2341928..52b5857 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
@@ -106,6 +106,23 @@
}
@Test
+ fun testDismissesOnFocusLoss() {
+ val container = initializeContainer()
+ waitForIdleSync()
+
+ verify(callback).onDialogAnimatedIn()
+
+ container.onWindowFocusChanged(false)
+ waitForIdleSync()
+
+ verify(callback).onDismissed(
+ eq(AuthDialogCallback.DISMISSED_USER_CANCELED),
+ eq<ByteArray?>(null) /* credentialAttestation */
+ )
+ assertThat(container.parent).isNull()
+ }
+
+ @Test
fun testActionAuthenticated_sendsDismissedAuthenticated() {
val container = initializeContainer()
container.mBiometricCallback.onAction(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsBpViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsBpViewControllerTest.kt
deleted file mode 100644
index a52c4a3..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsBpViewControllerTest.kt
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.biometrics
-
-import android.app.Instrumentation
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import android.testing.ViewUtils
-import androidx.test.filters.SmallTest
-import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
-import com.android.internal.jank.InteractionJankMonitor
-import com.android.internal.logging.testing.UiEventLoggerFake
-import com.android.systemui.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.broadcast.BroadcastSender
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.statusbar.StatusBarStateControllerImpl
-import com.android.systemui.statusbar.phone.SystemUIDialogManager
-import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager
-import com.android.systemui.util.mockito.any
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.spy
-import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
-import org.mockito.junit.MockitoJUnit
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@TestableLooper.RunWithLooper
-class UdfpsBpViewControllerTest : SysuiTestCase() {
-
- @JvmField @Rule var rule = MockitoJUnit.rule()
-
- @Mock lateinit var dumpManager: DumpManager
- @Mock lateinit var systemUIDialogManager: SystemUIDialogManager
- @Mock lateinit var broadcastSender: BroadcastSender
- @Mock lateinit var interactionJankMonitor: InteractionJankMonitor
- @Mock lateinit var panelExpansionStateManager: PanelExpansionStateManager
-
- private lateinit var instrumentation: Instrumentation
- private lateinit var uiEventLogger: UiEventLoggerFake
- private lateinit var udfpsBpView: UdfpsBpView
- private lateinit var statusBarStateController: StatusBarStateControllerImpl
- private lateinit var udfpsBpViewController: UdfpsBpViewController
-
- @Before
- fun setup() {
- instrumentation = getInstrumentation()
- instrumentation.runOnMainSync { createUdfpsView() }
- instrumentation.waitForIdleSync()
-
- uiEventLogger = UiEventLoggerFake()
- statusBarStateController =
- StatusBarStateControllerImpl(uiEventLogger, dumpManager, interactionJankMonitor)
- udfpsBpViewController = UdfpsBpViewController(
- udfpsBpView,
- statusBarStateController,
- panelExpansionStateManager,
- systemUIDialogManager,
- broadcastSender,
- dumpManager)
- udfpsBpViewController.init()
- }
-
- @After
- fun tearDown() {
- if (udfpsBpViewController.isAttachedToWindow) {
- instrumentation.runOnMainSync { ViewUtils.detachView(udfpsBpView) }
- instrumentation.waitForIdleSync()
- }
- }
-
- private fun createUdfpsView() {
- context.setTheme(R.style.Theme_AppCompat)
- context.orCreateTestableResources.addOverride(
- com.android.internal.R.integer.config_udfps_illumination_transition_ms, 0)
- udfpsBpView = UdfpsBpView(context, null)
- }
-
- @Test
- fun addExpansionListener() {
- instrumentation.runOnMainSync { ViewUtils.attachView(udfpsBpView) }
- instrumentation.waitForIdleSync()
-
- // Both UdfpsBpViewController & UdfpsAnimationViewController add listener
- verify(panelExpansionStateManager, times(2)).addExpansionListener(any())
- }
-
- @Test
- fun removeExpansionListener() {
- instrumentation.runOnMainSync { ViewUtils.attachView(udfpsBpView) }
- instrumentation.waitForIdleSync()
- instrumentation.runOnMainSync { ViewUtils.detachView(udfpsBpView) }
- instrumentation.waitForIdleSync()
-
- // Both UdfpsBpViewController & UdfpsAnimationViewController remove listener
- verify(panelExpansionStateManager, times(2)).removeExpansionListener(any())
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
index 431739b..cb8358d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
@@ -40,7 +40,6 @@
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ActivityLaunchAnimator
-import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.LockscreenShadeTransitionController
@@ -103,7 +102,6 @@
@Mock private lateinit var udfpsView: UdfpsView
@Mock private lateinit var udfpsEnrollView: UdfpsEnrollView
@Mock private lateinit var activityLaunchAnimator: ActivityLaunchAnimator
- @Mock private lateinit var broadcastSender: BroadcastSender
@Captor private lateinit var layoutParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams>
private val onTouch = { _: View, _: MotionEvent, _: Boolean -> true }
@@ -133,8 +131,7 @@
keyguardUpdateMonitor, dialogManager, dumpManager, transitionController,
configurationController, systemClock, keyguardStateController,
unlockedScreenOffAnimationController, HAL_CONTROLS_ILLUMINATION, hbmProvider,
- REQUEST_ID, reason, controllerCallback, onTouch, activityLaunchAnimator,
- broadcastSender)
+ REQUEST_ID, reason, controllerCallback, onTouch, activityLaunchAnimator)
block()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index e7e8e73..946c52e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -66,7 +66,6 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.ActivityLaunchAnimator;
-import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.plugins.FalsingManager;
@@ -188,8 +187,6 @@
private ActivityLaunchAnimator mActivityLaunchAnimator;
@Mock
private AlternateUdfpsTouchProvider mAlternateTouchProvider;
- @Mock
- private BroadcastSender mBroadcastSender;
// Capture listeners so that they can be used to send events
@Captor private ArgumentCaptor<IUdfpsOverlayController> mOverlayCaptor;
@@ -270,7 +267,6 @@
mLatencyTracker,
mActivityLaunchAnimator,
Optional.of(mAlternateTouchProvider),
- mBroadcastSender,
mBiometricsExecutor);
verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
mOverlayController = mOverlayCaptor.getValue();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
index 18ee791..187210a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
@@ -47,7 +47,9 @@
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.junit.MockitoJUnit
import org.mockito.Mockito.`when` as whenever
@@ -55,6 +57,7 @@
private const val KEY_OLD = "TEST_KEY_OLD"
private const val PACKAGE = "PKG"
private const val SESSION_KEY = "SESSION_KEY"
+private const val DEVICE_ID = "DEVICE_ID"
private const val DEVICE_NAME = "DEVICE_NAME"
private const val REMOTE_DEVICE_NAME = "REMOTE_DEVICE_NAME"
@@ -457,6 +460,89 @@
}
@Test
+ fun deviceIdChanged_informListener() {
+ // GIVEN a notification is added, with a particular device connected
+ whenever(device.id).thenReturn(DEVICE_ID)
+ manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+
+ // and later the manager gets a new device ID
+ val deviceCallback = captureCallback()
+ val updatedId = DEVICE_ID + "_new"
+ whenever(device.id).thenReturn(updatedId)
+ deviceCallback.onDeviceListUpdate(mutableListOf(device))
+
+ // THEN the listener gets the updated info
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+
+ val dataCaptor = ArgumentCaptor.forClass(MediaDeviceData::class.java)
+ verify(listener, times(2)).onMediaDeviceChanged(eq(KEY), any(), dataCaptor.capture())
+
+ val firstDevice = dataCaptor.allValues.get(0)
+ assertThat(firstDevice.id).isEqualTo(DEVICE_ID)
+
+ val secondDevice = dataCaptor.allValues.get(1)
+ assertThat(secondDevice.id).isEqualTo(updatedId)
+ }
+
+ @Test
+ fun deviceNameChanged_informListener() {
+ // GIVEN a notification is added, with a particular device connected
+ whenever(device.id).thenReturn(DEVICE_ID)
+ whenever(device.name).thenReturn(DEVICE_NAME)
+ manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+
+ // and later the manager gets a new device name
+ val deviceCallback = captureCallback()
+ val updatedName = DEVICE_NAME + "_new"
+ whenever(device.name).thenReturn(updatedName)
+ deviceCallback.onDeviceListUpdate(mutableListOf(device))
+
+ // THEN the listener gets the updated info
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+
+ val dataCaptor = ArgumentCaptor.forClass(MediaDeviceData::class.java)
+ verify(listener, times(2)).onMediaDeviceChanged(eq(KEY), any(), dataCaptor.capture())
+
+ val firstDevice = dataCaptor.allValues.get(0)
+ assertThat(firstDevice.name).isEqualTo(DEVICE_NAME)
+
+ val secondDevice = dataCaptor.allValues.get(1)
+ assertThat(secondDevice.name).isEqualTo(updatedName)
+ }
+
+ @Test
+ fun deviceIconChanged_doesNotCallListener() {
+ // GIVEN a notification is added, with a particular device connected
+ whenever(device.id).thenReturn(DEVICE_ID)
+ whenever(device.name).thenReturn(DEVICE_NAME)
+ val firstIcon = mock(Drawable::class.java)
+ whenever(device.icon).thenReturn(firstIcon)
+ manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+
+ val dataCaptor = ArgumentCaptor.forClass(MediaDeviceData::class.java)
+ verify(listener).onMediaDeviceChanged(eq(KEY), any(), dataCaptor.capture())
+
+ // and later the manager gets a callback with only the icon changed
+ val deviceCallback = captureCallback()
+ val secondIcon = mock(Drawable::class.java)
+ whenever(device.icon).thenReturn(secondIcon)
+ deviceCallback.onDeviceListUpdate(mutableListOf(device))
+
+ // THEN the listener is not called again
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+ verifyNoMoreInteractions(listener)
+ }
+
+ @Test
fun testRemotePlaybackDeviceOverride() {
whenever(route.name).thenReturn(DEVICE_NAME)
val deviceData = MediaDeviceData(false, null, REMOTE_DEVICE_NAME, null)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index 7c53388..e3b5059 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -27,6 +27,7 @@
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
+import android.media.AudioManager;
import android.media.session.MediaController;
import android.media.session.MediaSessionManager;
import android.media.session.PlaybackState;
@@ -84,6 +85,7 @@
private NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock(
NearbyMediaDevicesManager.class);
private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
+ private final AudioManager mAudioManager = mock(AudioManager.class);
private List<MediaController> mMediaControllers = new ArrayList<>();
private MediaOutputBaseDialogImpl mMediaOutputBaseDialogImpl;
@@ -108,7 +110,7 @@
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE,
mMediaSessionManager, mLocalBluetoothManager, mStarter,
mNotificationEntryManager, mDialogLaunchAnimator,
- Optional.of(mNearbyMediaDevicesManager));
+ Optional.of(mNearbyMediaDevicesManager), mAudioManager);
mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext, mBroadcastSender,
mMediaOutputController);
mMediaOutputBaseDialogImpl.onCreate(new Bundle());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
index d2dae74..feed334 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
@@ -31,6 +31,7 @@
import android.app.Notification;
import android.content.Context;
import android.graphics.drawable.Icon;
+import android.media.AudioManager;
import android.media.MediaDescription;
import android.media.MediaMetadata;
import android.media.NearbyDevice;
@@ -95,6 +96,7 @@
private MediaMetadata mMediaMetadata = mock(MediaMetadata.class);
private RoutingSessionInfo mRemoteSessionInfo = mock(RoutingSessionInfo.class);
private ActivityStarter mStarter = mock(ActivityStarter.class);
+ private AudioManager mAudioManager = mock(AudioManager.class);
private CommonNotifCollection mNotifCollection = mock(CommonNotifCollection.class);
private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
private final NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock(
@@ -123,7 +125,7 @@
mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME,
mMediaSessionManager, mLocalBluetoothManager, mStarter,
mNotifCollection, mDialogLaunchAnimator,
- Optional.of(mNearbyMediaDevicesManager));
+ Optional.of(mNearbyMediaDevicesManager), mAudioManager);
mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager);
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
MediaDescription.Builder builder = new MediaDescription.Builder();
@@ -175,7 +177,7 @@
mMediaOutputController = new MediaOutputController(mSpyContext, null,
mMediaSessionManager, mLocalBluetoothManager, mStarter,
mNotifCollection, mDialogLaunchAnimator,
- Optional.of(mNearbyMediaDevicesManager));
+ Optional.of(mNearbyMediaDevicesManager), mAudioManager);
mMediaOutputController.start(mCb);
@@ -204,7 +206,7 @@
mMediaOutputController = new MediaOutputController(mSpyContext, null,
mMediaSessionManager, mLocalBluetoothManager, mStarter,
mNotifCollection, mDialogLaunchAnimator,
- Optional.of(mNearbyMediaDevicesManager));
+ Optional.of(mNearbyMediaDevicesManager), mAudioManager);
mMediaOutputController.start(mCb);
@@ -509,7 +511,7 @@
mMediaOutputController = new MediaOutputController(mSpyContext, null,
mMediaSessionManager, mLocalBluetoothManager, mStarter,
mNotifCollection, mDialogLaunchAnimator,
- Optional.of(mNearbyMediaDevicesManager));
+ Optional.of(mNearbyMediaDevicesManager), mAudioManager);
assertThat(mMediaOutputController.getNotificationIcon()).isNull();
}
@@ -569,4 +571,24 @@
assertThat(mMediaOutputController.getNotificationIcon()).isNull();
}
+
+ @Test
+ public void isVolumeControlEnabled_isCastWithVolumeFixed_returnsFalse() {
+ when(mMediaDevice1.getDeviceType()).thenReturn(
+ MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE);
+
+ when(mMediaDevice1.isVolumeFixed()).thenReturn(true);
+
+ assertThat(mMediaOutputController.isVolumeControlEnabled(mMediaDevice1)).isFalse();
+ }
+
+ @Test
+ public void isVolumeControlEnabled_isCastWithVolumeNotFixed_returnsTrue() {
+ when(mMediaDevice1.getDeviceType()).thenReturn(
+ MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE);
+
+ when(mMediaDevice1.isVolumeFixed()).thenReturn(false);
+
+ assertThat(mMediaOutputController.isVolumeControlEnabled(mMediaDevice1)).isTrue();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
index e6ad6ed..6786ad0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
@@ -24,6 +24,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.media.AudioManager;
import android.media.MediaRoute2Info;
import android.media.session.MediaController;
import android.media.session.MediaSessionManager;
@@ -82,6 +83,7 @@
private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
private final NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock(
NearbyMediaDevicesManager.class);
+ private final AudioManager mAudioManager = mock(AudioManager.class);
private List<MediaController> mMediaControllers = new ArrayList<>();
private MediaOutputDialog mMediaOutputDialog;
@@ -101,7 +103,7 @@
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE,
mMediaSessionManager, mLocalBluetoothManager, mStarter,
mNotificationEntryManager, mDialogLaunchAnimator,
- Optional.of(mNearbyMediaDevicesManager));
+ Optional.of(mNearbyMediaDevicesManager), mAudioManager);
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
mMediaOutputDialog = new MediaOutputDialog(mContext, false, mBroadcastSender,
mMediaOutputController, mUiEventLogger);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
index 0cdde07..379bb4f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
@@ -21,6 +21,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.media.AudioManager;
import android.media.session.MediaSessionManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -68,6 +69,7 @@
private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
private NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock(
NearbyMediaDevicesManager.class);
+ private final AudioManager mAudioManager = mock(AudioManager.class);
private MediaOutputGroupDialog mMediaOutputGroupDialog;
private MediaOutputController mMediaOutputController;
@@ -78,7 +80,7 @@
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE,
mMediaSessionManager, mLocalBluetoothManager, mStarter,
mNotificationEntryManager, mDialogLaunchAnimator,
- Optional.of(mNearbyMediaDevicesManager));
+ Optional.of(mNearbyMediaDevicesManager), mAudioManager);
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false, mBroadcastSender,
mMediaOutputController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java
index 63dca3b..0badd861 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java
@@ -146,6 +146,20 @@
Assert.assertTrue(cam.getChroma() <= 8.0);
}
+ @Test
+ @SuppressWarnings("ResultOfMethodCallIgnored")
+ public void testToString() {
+ new ColorScheme(Color.TRANSPARENT, false /* darkTheme */).toString();
+ new ColorScheme(Color.argb(0, 0, 0, 0xf), false /* darkTheme */).toString();
+ new ColorScheme(Color.argb(0xff, 0xff, 0, 0), false /* darkTheme */).toString();
+ new ColorScheme(0xFFFFFFFF, false /* darkTheme */).toString();
+
+ new ColorScheme(Color.TRANSPARENT, true /* darkTheme */).toString();
+ new ColorScheme(Color.argb(0, 0, 0, 0xf), true /* darkTheme */).toString();
+ new ColorScheme(0xFFFF0000, true /* darkTheme */).toString();
+ new ColorScheme(0xFFFFFFFF, true /* darkTheme */).toString();
+ }
+
/**
* Generate xml for SystemPaletteTest#testThemeStyles().
*/
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
index e237a5c..60cfd72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
@@ -13,18 +13,24 @@
*/
package com.android.systemui.qs
+import android.graphics.Rect
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
+import android.testing.ViewUtils
import android.view.View
-import android.view.ViewGroup
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.accessibility.AccessibilityNodeInfo
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.qs.tileimpl.QSIconViewImpl
+import com.android.systemui.qs.tileimpl.QSTileViewImpl
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -36,37 +42,40 @@
@RunWithLooper
@SmallTest
class QSPanelTest : SysuiTestCase() {
- private lateinit var mTestableLooper: TestableLooper
- private lateinit var mQsPanel: QSPanel
+ private lateinit var testableLooper: TestableLooper
+ private lateinit var qsPanel: QSPanel
- private lateinit var mParentView: ViewGroup
-
- private lateinit var mFooter: View
+ private lateinit var footer: View
@Before
@Throws(Exception::class)
fun setup() {
MockitoAnnotations.initMocks(this)
- mTestableLooper = TestableLooper.get(this)
+ testableLooper = TestableLooper.get(this)
- mTestableLooper.runWithLooper {
- mQsPanel = QSPanel(mContext, null)
- mQsPanel.initialize()
+ testableLooper.runWithLooper {
+ qsPanel = QSPanel(context, null)
+ qsPanel.mUsingMediaPlayer = true
+
+ qsPanel.initialize()
// QSPanel inflates a footer inside of it, mocking it here
- mFooter = LinearLayout(mContext).apply { id = R.id.qs_footer }
- mQsPanel.addView(mFooter)
- mQsPanel.onFinishInflate()
+ footer = LinearLayout(context).apply { id = R.id.qs_footer }
+ qsPanel.addView(footer, MATCH_PARENT, 100)
+ qsPanel.onFinishInflate()
// Provides a parent with non-zero size for QSPanel
- mParentView = FrameLayout(mContext).apply {
- addView(mQsPanel)
- }
+ ViewUtils.attachView(qsPanel)
}
}
+ @After
+ fun tearDown() {
+ ViewUtils.detachView(qsPanel)
+ }
+
@Test
fun testHasCollapseAccessibilityAction() {
- val info = AccessibilityNodeInfo(mQsPanel)
- mQsPanel.onInitializeAccessibilityNodeInfo(info)
+ val info = AccessibilityNodeInfo(qsPanel)
+ qsPanel.onInitializeAccessibilityNodeInfo(info)
assertThat(info.actions and AccessibilityNodeInfo.ACTION_COLLAPSE).isNotEqualTo(0)
assertThat(info.actions and AccessibilityNodeInfo.ACTION_EXPAND).isEqualTo(0)
@@ -75,9 +84,79 @@
@Test
fun testCollapseActionCallsRunnable() {
val mockRunnable = mock(Runnable::class.java)
- mQsPanel.setCollapseExpandAction(mockRunnable)
+ qsPanel.setCollapseExpandAction(mockRunnable)
- mQsPanel.performAccessibilityAction(AccessibilityNodeInfo.ACTION_COLLAPSE, null)
+ qsPanel.performAccessibilityAction(AccessibilityNodeInfo.ACTION_COLLAPSE, null)
verify(mockRunnable).run()
}
+
+ @Test
+ fun testTilesFooterVisibleRTLLandscapeMedia() {
+ qsPanel.layoutDirection = View.LAYOUT_DIRECTION_RTL
+ // We need at least a tile so the layout has a height
+ qsPanel.tileLayout?.addTile(
+ QSPanelControllerBase.TileRecord(
+ mock(QSTile::class.java),
+ QSTileViewImpl(context, QSIconViewImpl(context))
+ )
+ )
+
+ val mediaView = FrameLayout(context)
+ mediaView.addView(View(context), MATCH_PARENT, 800)
+
+ qsPanel.setUsingHorizontalLayout(/* horizontal */ true, mediaView, /* force */ true)
+ qsPanel.measure(
+ /* width */ View.MeasureSpec.makeMeasureSpec(3000, View.MeasureSpec.EXACTLY),
+ /* height */ View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY)
+ )
+ qsPanel.layout(0, 0, qsPanel.measuredWidth, qsPanel.measuredHeight)
+
+ val tiles = qsPanel.tileLayout as View
+ // Tiles are effectively to the right of media
+ assertThat(mediaView isLeftOf tiles)
+ assertThat(tiles.isVisibleToUser).isTrue()
+
+ assertThat(mediaView isLeftOf footer)
+ assertThat(footer.isVisibleToUser).isTrue()
+ }
+
+ @Test
+ fun testTilesFooterVisibleLandscapeMedia() {
+ qsPanel.layoutDirection = View.LAYOUT_DIRECTION_LTR
+ // We need at least a tile so the layout has a height
+ qsPanel.tileLayout?.addTile(
+ QSPanelControllerBase.TileRecord(
+ mock(QSTile::class.java),
+ QSTileViewImpl(context, QSIconViewImpl(context))
+ )
+ )
+
+ val mediaView = FrameLayout(context)
+ mediaView.addView(View(context), MATCH_PARENT, 800)
+
+ qsPanel.setUsingHorizontalLayout(/* horizontal */ true, mediaView, /* force */ true)
+ qsPanel.measure(
+ /* width */ View.MeasureSpec.makeMeasureSpec(3000, View.MeasureSpec.EXACTLY),
+ /* height */ View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY)
+ )
+ qsPanel.layout(0, 0, qsPanel.measuredWidth, qsPanel.measuredHeight)
+
+ val tiles = qsPanel.tileLayout as View
+ // Tiles are effectively to the left of media
+ assertThat(tiles isLeftOf mediaView)
+ assertThat(tiles.isVisibleToUser).isTrue()
+
+ assertThat(footer isLeftOf mediaView)
+ assertThat(footer.isVisibleToUser).isTrue()
+ }
+
+ private infix fun View.isLeftOf(other: View): Boolean {
+ val rect = Rect()
+ getBoundsOnScreen(rect)
+ val thisRight = rect.right
+
+ other.getBoundsOnScreen(rect)
+
+ return thisRight <= rect.left
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
index f76b50a..bd4b94e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
@@ -189,6 +189,67 @@
assertThat(tracker.userProfiles.map { it.id }).containsExactly(tracker.userId, profileID)
}
+ fun testManagedProfileUnavailable() {
+ tracker.initialize(0)
+ val profileID = tracker.userId + 10
+
+ `when`(userManager.getProfiles(anyInt())).thenAnswer { invocation ->
+ val id = invocation.getArgument<Int>(0)
+ val info = UserInfo(id, "", UserInfo.FLAG_FULL)
+ val infoProfile = UserInfo(
+ id + 10,
+ "",
+ "",
+ UserInfo.FLAG_MANAGED_PROFILE or UserInfo.FLAG_QUIET_MODE,
+ UserManager.USER_TYPE_PROFILE_MANAGED
+ )
+ infoProfile.profileGroupId = id
+ listOf(info, infoProfile)
+ }
+
+ val intent = Intent(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)
+ .putExtra(Intent.EXTRA_USER, UserHandle.of(profileID))
+ tracker.onReceive(context, intent)
+
+ assertThat(tracker.userProfiles.map { it.id }).containsExactly(tracker.userId, profileID)
+ }
+
+ fun testManagedProfileStartedAndRemoved() {
+ tracker.initialize(0)
+ val profileID = tracker.userId + 10
+
+ `when`(userManager.getProfiles(anyInt())).thenAnswer { invocation ->
+ val id = invocation.getArgument<Int>(0)
+ val info = UserInfo(id, "", UserInfo.FLAG_FULL)
+ val infoProfile = UserInfo(
+ id + 10,
+ "",
+ "",
+ UserInfo.FLAG_MANAGED_PROFILE,
+ UserManager.USER_TYPE_PROFILE_MANAGED
+ )
+ infoProfile.profileGroupId = id
+ listOf(info, infoProfile)
+ }
+
+ // Managed profile started
+ val intent = Intent(Intent.ACTION_MANAGED_PROFILE_UNLOCKED)
+ .putExtra(Intent.EXTRA_USER, UserHandle.of(profileID))
+ tracker.onReceive(context, intent)
+
+ assertThat(tracker.userProfiles.map { it.id }).containsExactly(tracker.userId, profileID)
+
+ `when`(userManager.getProfiles(anyInt())).thenAnswer { invocation ->
+ listOf(UserInfo(invocation.getArgument(0), "", UserInfo.FLAG_FULL))
+ }
+
+ val intent2 = Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED)
+ .putExtra(Intent.EXTRA_USER, UserHandle.of(profileID))
+ tracker.onReceive(context, intent2)
+
+ assertThat(tracker.userProfiles.map { it.id }).containsExactly(tracker.userId)
+ }
+
@Test
fun testCallbackNotCalledOnAdd() {
tracker.initialize(0)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
index 5804ad4..769143d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
@@ -29,6 +29,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import android.app.ActivityManager;
@@ -57,6 +58,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
import java.util.ArrayList;
@@ -72,6 +74,7 @@
private int mId;
private NotificationEntry mEntry;
+ private NotificationChannel mChannel = Mockito.mock(NotificationChannel.class);
private final FakeSystemClock mClock = new FakeSystemClock();
@Before
@@ -85,10 +88,13 @@
.setPkg(TEST_PACKAGE_NAME)
.setOpPkg(TEST_PACKAGE_NAME)
.setUid(TEST_UID)
+ .setChannel(mChannel)
.setId(mId++)
.setNotification(n.build())
.setUser(new UserHandle(ActivityManager.getCurrentUser()))
.build();
+
+ doReturn(false).when(mChannel).isBlockable();
}
@Test
@@ -100,6 +106,44 @@
}
@Test
+ public void testBlockableEntryWhenCritical() {
+ doReturn(true).when(mChannel).isBlockable();
+
+ assertTrue(mEntry.isBlockable());
+ }
+
+
+ @Test
+ public void testBlockableEntryWhenCriticalAndChannelNotBlockable() {
+ doReturn(true).when(mChannel).isBlockable();
+ doReturn(true).when(mChannel).isImportanceLockedByCriticalDeviceFunction();
+
+ assertTrue(mEntry.isBlockable());
+ }
+
+ @Test
+ public void testNonBlockableEntryWhenCriticalAndChannelNotBlockable() {
+ doReturn(false).when(mChannel).isBlockable();
+ doReturn(true).when(mChannel).isImportanceLockedByCriticalDeviceFunction();
+
+ assertFalse(mEntry.isBlockable());
+ }
+
+ @Test
+ public void testBlockableWhenEntryHasNoChannel() {
+ StatusBarNotification sbn = new SbnBuilder().build();
+ Ranking ranking = new RankingBuilder()
+ .setChannel(null)
+ .setKey(sbn.getKey())
+ .build();
+
+ NotificationEntry entry =
+ new NotificationEntry(sbn, ranking, mClock.uptimeMillis());
+
+ assertFalse(entry.isBlockable());
+ }
+
+ @Test
public void testIsExemptFromDndVisualSuppression_media() {
Notification.Builder n = new Notification.Builder(mContext, "")
.setStyle(new Notification.MediaStyle()
@@ -117,7 +161,8 @@
@Test
public void testIsExemptFromDndVisualSuppression_system() {
- mEntry.mIsSystemNotification = true;
+ doReturn(true).when(mChannel).isImportanceLockedByCriticalDeviceFunction();
+ doReturn(false).when(mChannel).isBlockable();
assertTrue(mEntry.isExemptFromDndVisualSuppression());
assertFalse(mEntry.shouldSuppressAmbient());
@@ -128,7 +173,7 @@
NotificationEntry entry = new NotificationEntryBuilder()
.setUid(UID_NORMAL)
.build();
- entry.mIsSystemNotification = true;
+ doReturn(true).when(mChannel).isImportanceLockedByCriticalDeviceFunction();
modifyRanking(entry).setSuppressedVisualEffects(SUPPRESSED_EFFECT_AMBIENT).build();
modifySbn(entry)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
index 52bacd2..d082d74 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.collection.coordinator;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -74,7 +75,7 @@
KeyguardCoordinator keyguardCoordinator = new KeyguardCoordinator(
mStatusBarStateController,
mKeyguardUpdateMonitor, mHighPriorityProvider, mSectionHeaderVisibilityProvider,
- mKeyguardNotificationVisibilityProvider);
+ mKeyguardNotificationVisibilityProvider, mock(SharedCoordinatorLogger.class));
mEntry = new NotificationEntryBuilder()
.setUser(new UserHandle(NOTIF_USER_ID))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
index f4d8405..15c1cb7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.collection.coordinator;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
@@ -30,6 +31,7 @@
import static org.mockito.Mockito.when;
import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.testing.AndroidTestingRunner;
@@ -185,7 +187,7 @@
// WHEN it's not dozing (showing the notification list)
when(mStatusBarStateController.isDozing()).thenReturn(false);
-
+
// THEN filter out the notification
assertTrue(mCapturedDozingFilter.shouldFilterOut(mEntry, 0));
}
@@ -277,6 +279,7 @@
private RankingBuilder getRankingForUnfilteredNotif() {
return new RankingBuilder(mEntry.getRanking())
+ .setChannel(new NotificationChannel("id", null, IMPORTANCE_DEFAULT))
.setSuppressedVisualEffects(0)
.setSuspended(false);
}
@@ -292,7 +295,7 @@
mEntry.setRanking(new RankingBuilder(mEntry.getRanking())
.setImportance(ambient
? NotificationManager.IMPORTANCE_MIN
- : NotificationManager.IMPORTANCE_DEFAULT)
+ : IMPORTANCE_DEFAULT)
.build());
assertEquals(ambient, mEntry.getRanking().isAmbient());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
index 8a2dc26..90627cb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
@@ -36,6 +36,7 @@
import static org.mockito.Mockito.when;
import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.PendingIntent;
import android.content.Intent;
import android.graphics.drawable.Icon;
@@ -529,6 +530,7 @@
.setPkg("a")
.setOpPkg("a")
.setTag("a")
+ .setChannel(new NotificationChannel("a", null, importance))
.setNotification(n)
.setImportance(importance)
.build();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index c36737c..b1bf971 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -58,6 +58,7 @@
import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
import com.android.systemui.statusbar.notification.FeedbackIcon;
import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import org.junit.Assert;
@@ -65,6 +66,7 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@@ -412,27 +414,15 @@
public void testGetIsNonblockable() throws Exception {
ExpandableNotificationRow row =
mNotificationTestHelper.createRow(mNotificationTestHelper.createNotification());
-
- assertFalse(row.getIsNonblockable());
- }
-
- @Test
- public void testGetIsNonblockable_criticalDeviceFunction() throws Exception {
- ExpandableNotificationRow row =
- mNotificationTestHelper.createRow(mNotificationTestHelper.createNotification());
- row.getEntry().getChannel().setImportanceLockedByCriticalDeviceFunction(true);
- row.getEntry().getChannel().setBlockable(false);
+ row.setEntry(null);
assertTrue(row.getIsNonblockable());
- }
- @Test
- public void testGetIsNonblockable_criticalDeviceFunction_butBlockable() throws Exception {
- ExpandableNotificationRow row =
- mNotificationTestHelper.createRow(mNotificationTestHelper.createNotification());
- row.getEntry().getChannel().setImportanceLockedByCriticalDeviceFunction(true);
- row.getEntry().getChannel().setBlockable(true);
+ NotificationEntry entry = mock(NotificationEntry.class);
+ Mockito.doReturn(false, true).when(entry).isBlockable();
+ row.setEntry(entry);
+ assertTrue(row.getIsNonblockable());
assertFalse(row.getIsNonblockable());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index 16f934b..2faff0c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -39,6 +39,7 @@
import android.app.IWallpaperManager;
import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.WallpaperManager;
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
@@ -718,6 +719,7 @@
.setPkg("a")
.setOpPkg("a")
.setTag("a")
+ .setChannel(new NotificationChannel("id", null, IMPORTANCE_HIGH))
.setNotification(n)
.setImportance(IMPORTANCE_HIGH)
.setSuppressedVisualEffects(SUPPRESSED_EFFECT_PEEK)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
index 018c453..d47644f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
@@ -889,7 +889,8 @@
updateSmallestScreenWidth(300);
when(mResources.getBoolean(
com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
- when(mUserManager.isUserSwitcherEnabled()).thenReturn(true);
+ when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
+ when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(true);
updateSmallestScreenWidth(800);
@@ -897,6 +898,34 @@
}
@Test
+ public void testFinishInflate_userSwitcherDisabled_doNotInflateUserSwitchView() {
+ givenViewAttached();
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
+ when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
+ when(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
+ .thenReturn(false);
+
+ mNotificationPanelViewController.onFinishInflate();
+
+ verify(mUserSwitcherStubView, never()).inflate();
+ }
+
+ @Test
+ public void testReInflateViews_userSwitcherDisabled_doNotInflateUserSwitchView() {
+ givenViewAttached();
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
+ when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
+ when(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
+ .thenReturn(false);
+
+ mNotificationPanelViewController.reInflateViews();
+
+ verify(mUserSwitcherStubView, never()).inflate();
+ }
+
+ @Test
public void testCanCollapsePanelOnTouch_trueForKeyGuard() {
mStatusBarStateController.setState(KEYGUARD);
@@ -1298,7 +1327,8 @@
}
private void updateMultiUserSetting(boolean enabled) {
- when(mUserManager.isUserSwitcherEnabled()).thenReturn(enabled);
+ when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
+ when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(enabled);
final ArgumentCaptor<ContentObserver> observerCaptor =
ArgumentCaptor.forClass(ContentObserver.class);
verify(mContentResolver)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt
index 0032452..de40b7f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt
@@ -206,7 +206,9 @@
given(taskbarVisible = false,
navigationMode = BUTTONS_NAVIGATION,
insets = windowInsets().withStableBottom())
- then(expectedContainerPadding = 0, expectedQsPadding = STABLE_INSET_BOTTOM)
+ then(expectedContainerPadding = 0,
+ expectedNotificationsMargin = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN,
+ expectedQsPadding = STABLE_INSET_BOTTOM)
}
@Test
diff --git a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
index 09a05bb..3d24588 100644
--- a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
+++ b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
@@ -124,15 +124,21 @@
private static final String CAMERA_EXTENSION_VERSION_NAME =
"androidx.camera.extensions.impl.ExtensionVersionImpl";
- private static final String LATEST_VERSION = "1.2.0";
+ private static final String LATEST_VERSION = "1.3.0";
+ // No support for the init sequence
private static final String NON_INIT_VERSION_PREFIX = "1.0";
+ // Support advanced API and latency queries
private static final String ADVANCED_VERSION_PREFIX = "1.2";
+ // Support for the capture request & result APIs
private static final String RESULTS_VERSION_PREFIX = "1.3";
+ private static final String[] ADVANCED_VERSION_PREFIXES = {ADVANCED_VERSION_PREFIX,
+ RESULTS_VERSION_PREFIX};
private static final String[] SUPPORTED_VERSION_PREFIXES = {RESULTS_VERSION_PREFIX,
ADVANCED_VERSION_PREFIX, "1.1", NON_INIT_VERSION_PREFIX};
private static final boolean EXTENSIONS_PRESENT = checkForExtensions();
private static final String EXTENSIONS_VERSION = EXTENSIONS_PRESENT ?
(new ExtensionVersionImpl()).checkApiVersion(LATEST_VERSION) : null;
+ private static final boolean LATENCY_API_SUPPORTED = checkForLatencyAPI();
private static final boolean ADVANCED_API_SUPPORTED = checkForAdvancedAPI();
private static final boolean INIT_API_SUPPORTED = EXTENSIONS_PRESENT &&
(!EXTENSIONS_VERSION.startsWith(NON_INIT_VERSION_PREFIX));
@@ -143,19 +149,35 @@
private HashMap<String, Long> mMetadataVendorIdMap = new HashMap<>();
private CameraManager mCameraManager;
- private static boolean checkForAdvancedAPI() {
- if (EXTENSIONS_PRESENT && EXTENSIONS_VERSION.startsWith(ADVANCED_VERSION_PREFIX)) {
- try {
- return (new ExtensionVersionImpl()).isAdvancedExtenderImplemented();
- } catch (NoSuchMethodError e) {
- // This could happen in case device specific extension implementations are using an
- // older extension API but incorrectly set the extension version.
+ private static boolean checkForLatencyAPI() {
+ if (!EXTENSIONS_PRESENT) {
+ return false;
+ }
+
+ for (String advancedVersions : ADVANCED_VERSION_PREFIXES) {
+ if (EXTENSIONS_VERSION.startsWith(advancedVersions)) {
+ return true;
}
}
return false;
}
+ private static boolean checkForAdvancedAPI() {
+ if (!checkForLatencyAPI()) {
+ return false;
+ }
+
+ try {
+ return (new ExtensionVersionImpl()).isAdvancedExtenderImplemented();
+ } catch (NoSuchMethodError e) {
+ // This could happen in case device specific extension implementations are using
+ // an older extension API but incorrectly set the extension version.
+ }
+
+ return false;
+ }
+
private static boolean checkForExtensions() {
try {
Class.forName(CAMERA_EXTENSION_VERSION_NAME);
@@ -292,7 +314,7 @@
if (INIT_API_SUPPORTED) {
if (mActiveClients.isEmpty()) {
InitializerFuture status = new InitializerFuture();
- InitializerImpl.init(EXTENSIONS_VERSION, ctx, new InitializeHandler(status),
+ InitializerImpl.init(LATEST_VERSION, ctx, new InitializeHandler(status),
new HandlerExecutor(mHandler));
boolean initSuccess;
try {
@@ -1447,7 +1469,7 @@
@Override
public LatencyRange getEstimatedCaptureLatencyRange(
android.hardware.camera2.extension.Size outputSize) {
- if (EXTENSIONS_VERSION.startsWith(ADVANCED_VERSION_PREFIX)) {
+ if (LATENCY_API_SUPPORTED) {
Size sz = new Size(outputSize.width, outputSize.height);
Range<Long> latencyRange = mImageExtender.getEstimatedCaptureLatencyRange(sz);
if (latencyRange != null) {
diff --git a/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java b/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java
index c6e595b..01cee33 100644
--- a/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java
+++ b/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java
@@ -174,7 +174,7 @@
public void logAndEndEvent() {
if (!mEventInternal.isPresent()) {
- Slog.wtf(null, "Shouldn't be logging AutofillPresentationEventReported again for same "
+ Slog.w(TAG, "Shouldn't be logging AutofillPresentationEventReported again for same "
+ "event");
return;
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index a4eaef9..8368b4d 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -63,6 +63,12 @@
import static android.os.Process.ZYGOTE_POLICY_FLAG_EMPTY;
import static com.android.internal.messages.nano.SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICE_BG_LAUNCH;
+import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED;
+import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD;
+import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_HOT;
+import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM;
+import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED__REQUEST_TYPE__BIND;
+import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED__REQUEST_TYPE__START;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKGROUND_CHECK;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOREGROUND_SERVICE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
@@ -522,8 +528,9 @@
+ " delayedStop=" + r.delayedStop);
} else {
try {
- startServiceInnerLocked(this, r.pendingStarts.get(0).intent, r, false,
- true);
+ final ServiceRecord.StartItem si = r.pendingStarts.get(0);
+ startServiceInnerLocked(this, si.intent, r, false, true, si.callingId,
+ r.startRequested);
} catch (TransactionTooLargeException e) {
// Ignore, nobody upstack cares.
}
@@ -865,6 +872,7 @@
if (unscheduleServiceRestartLocked(r, callingUid, false)) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r);
}
+ final boolean wasStartRequested = r.startRequested;
r.lastActivity = SystemClock.uptimeMillis();
r.startRequested = true;
r.delayedStop = false;
@@ -954,7 +962,8 @@
if (allowBackgroundActivityStarts) {
r.allowBgActivityStartsOnServiceStart(backgroundActivityStartsToken);
}
- ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
+ ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting,
+ callingUid, wasStartRequested);
return cmp;
}
@@ -1150,7 +1159,8 @@
}
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
- boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
+ boolean callerFg, boolean addToStarting, int callingUid, boolean wasStartRequested)
+ throws TransactionTooLargeException {
synchronized (mAm.mProcessStats.mLock) {
final ServiceState stracker = r.getTracker();
if (stracker != null) {
@@ -1177,6 +1187,15 @@
return new ComponentName("!!", error);
}
+ FrameworkStatsLog.write(SERVICE_REQUEST_EVENT_REPORTED, uid, callingUid,
+ ActivityManagerService.getShortAction(service.getAction()),
+ SERVICE_REQUEST_EVENT_REPORTED__REQUEST_TYPE__START, false,
+ r.app == null || r.app.getThread() == null
+ ? SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD
+ : (wasStartRequested || !r.getConnections().isEmpty()
+ ? SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_HOT
+ : SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM));
+
if (r.startRequested && addToStarting) {
boolean first = smap.mStartingBackground.size() == 0;
smap.mStartingBackground.add(r);
@@ -2876,6 +2895,8 @@
mAm.requireAllowedAssociationsLocked(s.appInfo.packageName);
}
+ final boolean wasStartRequested = s.startRequested;
+ final boolean hadConnections = !s.getConnections().isEmpty();
mAm.startAssociationLocked(callerApp.uid, callerApp.processName,
callerApp.mState.getCurProcState(), s.appInfo.uid, s.appInfo.longVersionCode,
s.instanceName, s.processName);
@@ -2962,6 +2983,15 @@
mAm.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
}
+ FrameworkStatsLog.write(SERVICE_REQUEST_EVENT_REPORTED, s.appInfo.uid, callingUid,
+ ActivityManagerService.getShortAction(service.getAction()),
+ SERVICE_REQUEST_EVENT_REPORTED__REQUEST_TYPE__BIND, false,
+ s.app == null || s.app.getThread() == null
+ ? SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD
+ : (wasStartRequested || hadConnections
+ ? SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_HOT
+ : SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM));
+
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
+ ": received=" + b.intent.received
+ " apps=" + b.intent.apps.size()
@@ -6917,7 +6947,8 @@
durationMs,
r.mStartForegroundCount,
ActivityManagerUtils.hashComponentNameForAtom(r.shortInstanceName),
- r.mFgsHasNotificationPermission);
+ r.mFgsHasNotificationPermission,
+ r.foregroundServiceType);
int event = 0;
if (state == FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 71a2848..a78c64b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5003,15 +5003,7 @@
final HostingRecord hostingRecord = app.getHostingRecord();
- final String action = hostingRecord.getAction();
- String shortAction = action;
- if (action != null) {
- // only log the last part of the action string to save stats data.
- int index = action.lastIndexOf(".");
- if (index != -1 && index != action.length() - 1) {
- shortAction = action.substring(index + 1);
- }
- }
+ String shortAction = getShortAction(hostingRecord.getAction());
FrameworkStatsLog.write(
FrameworkStatsLog.PROCESS_START_TIME,
app.info.uid,
@@ -5042,6 +5034,20 @@
}
}
+ /**
+ * @return The last part of the string of an intent's action.
+ */
+ static @Nullable String getShortAction(@Nullable String action) {
+ String shortAction = action;
+ if (action != null) {
+ int index = action.lastIndexOf('.');
+ if (index != -1 && index != action.length() - 1) {
+ shortAction = action.substring(index + 1);
+ }
+ }
+ return shortAction;
+ }
+
void checkTime(long startTime, String where) {
long now = SystemClock.uptimeMillis();
if ((now - startTime) > 50) {
@@ -14262,7 +14268,7 @@
oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
oldRecord.intent,
Activity.RESULT_CANCELED, null, null,
- false, false, oldRecord.userId);
+ false, false, oldRecord.userId, oldRecord.callingUid, callingUid);
} catch (RemoteException e) {
Slog.w(TAG, "Failure ["
+ queue.mQueueName + "] sending broadcast result of "
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index f7aa7c15..43d0de9 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -24,6 +24,11 @@
import static com.android.internal.util.FrameworkStatsLog.BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED;
import static com.android.internal.util.FrameworkStatsLog.BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED__EVENT__BOOT_COMPLETED;
import static com.android.internal.util.FrameworkStatsLog.BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED__EVENT__LOCKED_BOOT_COMPLETED;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__MANIFEST;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__RUNTIME;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_DEFERRAL;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_LIGHT;
@@ -316,7 +321,7 @@
}
private final void processCurBroadcastLocked(BroadcastRecord r,
- ProcessRecord app) throws RemoteException {
+ ProcessRecord app, int receiverType, int processTemperature) throws RemoteException {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + " for app " + app);
final IApplicationThread thread = app.getThread();
@@ -362,6 +367,10 @@
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + " DELIVERED for app " + app);
started = true;
+ FrameworkStatsLog.write(BROADCAST_DELIVERY_EVENT_REPORTED, app.uid,
+ r.callingUid == -1 ? Process.SYSTEM_UID : r.callingUid,
+ ActivityManagerService.getShortAction(r.intent.getAction()),
+ receiverType, processTemperature);
} finally {
if (!started) {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
@@ -398,7 +407,9 @@
}
try {
mPendingBroadcast = null;
- processCurBroadcastLocked(br, app);
+ processCurBroadcastLocked(br, app,
+ BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__MANIFEST,
+ BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD);
didSomething = true;
} catch (Exception e) {
Slog.w(TAG, "Exception in new application when starting receiver "
@@ -628,8 +639,8 @@
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
- boolean ordered, boolean sticky, int sendingUser)
- throws RemoteException {
+ boolean ordered, boolean sticky, int sendingUser,
+ int receiverUid, int callingUid) throws RemoteException {
// Send the intent to the receiver asynchronously using one-way binder calls.
if (app != null) {
final IApplicationThread thread = app.getThread();
@@ -663,6 +674,12 @@
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
+ FrameworkStatsLog.write(BROADCAST_DELIVERY_EVENT_REPORTED,
+ receiverUid == -1 ? Process.SYSTEM_UID : receiverUid,
+ callingUid == -1 ? Process.SYSTEM_UID : callingUid,
+ ActivityManagerService.getShortAction(intent.getAction()),
+ BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__RUNTIME,
+ BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM);
}
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
@@ -965,7 +982,8 @@
maybeReportBroadcastDispatchedEventLocked(r, filter.owningUid);
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
- r.resultExtras, r.ordered, r.initialSticky, r.userId);
+ r.resultExtras, r.ordered, r.initialSticky, r.userId,
+ filter.receiverList.uid, r.callingUid);
// parallel broadcasts are fire-and-forget, not bookended by a call to
// finishReceiverLocked(), so we manage their activity-start token here
if (filter.receiverList.app != null
@@ -1317,7 +1335,8 @@
}
performReceiveLocked(r.callerApp, r.resultTo,
new Intent(r.intent), r.resultCode,
- r.resultData, r.resultExtras, false, false, r.userId);
+ r.resultData, r.resultExtras, false, false, r.userId,
+ r.callingUid, r.callingUid);
logBootCompletedBroadcastCompletionLatencyIfPossible(r);
// Set this to null so that the reference
// (local and remote) isn't kept in the mBroadcastHistory.
@@ -1837,7 +1856,9 @@
app.addPackage(info.activityInfo.packageName,
info.activityInfo.applicationInfo.longVersionCode, mService.mProcessStats);
maybeAddAllowBackgroundActivityStartsToken(app, r);
- processCurBroadcastLocked(r, app);
+ processCurBroadcastLocked(r, app,
+ BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__MANIFEST,
+ BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when sending broadcast to "
diff --git a/services/core/java/com/android/server/audio/RotationHelper.java b/services/core/java/com/android/server/audio/RotationHelper.java
index d4f4245..eb8387f 100644
--- a/services/core/java/com/android/server/audio/RotationHelper.java
+++ b/services/core/java/com/android/server/audio/RotationHelper.java
@@ -20,12 +20,13 @@
import android.hardware.devicestate.DeviceStateManager;
import android.hardware.devicestate.DeviceStateManager.FoldStateListener;
import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerGlobal;
import android.media.AudioSystem;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.util.Log;
+import android.view.Display;
import android.view.Surface;
-import android.view.WindowManager;
/**
* Class to handle device rotation events for AudioService, and forward device rotation
@@ -48,6 +49,8 @@
private static final String TAG = "AudioService.RotationHelper";
+ private static final boolean DEBUG_ROTATION = false;
+
private static AudioDisplayListener sDisplayListener;
private static FoldStateListener sFoldStateListener;
@@ -98,8 +101,8 @@
// Even though we're responding to device orientation events,
// use display rotation so audio stays in sync with video/dialogs
// TODO(b/148458001): Support multi-display
- int newRotation = ((WindowManager) sContext.getSystemService(
- Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
+ int newRotation = DisplayManagerGlobal.getInstance()
+ .getDisplayInfo(Display.DEFAULT_DISPLAY).rotation;
synchronized(sRotationLock) {
if (newRotation != sDeviceRotation) {
sDeviceRotation = newRotation;
@@ -109,7 +112,9 @@
}
private static void publishRotation(int rotation) {
- Log.v(TAG, "publishing device rotation =" + rotation + " (x90deg)");
+ if (DEBUG_ROTATION) {
+ Log.i(TAG, "publishing device rotation =" + rotation + " (x90deg)");
+ }
switch (rotation) {
case Surface.ROTATION_0:
AudioSystem.setParameters("rotation=0");
@@ -159,6 +164,9 @@
@Override
public void onDisplayChanged(int displayId) {
+ if (DEBUG_ROTATION) {
+ Log.i(TAG, "onDisplayChanged diplayId:" + displayId);
+ }
updateOrientation();
}
}
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index cf63b69..6fd8841 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -1057,7 +1057,17 @@
public void recalculateSplines(boolean applyAdjustment, float[] adjustment) {
mCurrentBrightnessMapper.recalculateSplines(applyAdjustment, adjustment);
- updateAutoBrightness(true /*sendUpdate*/, false /*isManuallySet*/);
+
+ // If rbc is turned on, off or there is a change in strength, we want to reset the short
+ // term model. Since the nits range at which brightness now operates has changed due to
+ // RBC/strength change, any short term model based on the previous range should be
+ // invalidated.
+ resetShortTermModel();
+
+ // When rbc is turned on, we want to accommodate this change in the short term model.
+ if (applyAdjustment) {
+ setScreenBrightnessByUser(getAutomaticScreenBrightness());
+ }
}
private final class AutomaticBrightnessHandler extends Handler {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 6285ef1..d3e2966 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -485,7 +485,7 @@
mUiHandler = UiThread.getHandler();
mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, mDisplayDeviceRepo,
- new LogicalDisplayListener(), mSyncRoot, mHandler);
+ new LogicalDisplayListener(), mSyncRoot, mHandler, new DeviceStateToLayoutMap());
mDisplayModeDirector = new DisplayModeDirector(context, mHandler);
mBrightnessSynchronizer = new BrightnessSynchronizer(mContext);
Resources resources = mContext.getResources();
@@ -945,7 +945,8 @@
private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) {
synchronized (mSyncRoot) {
- final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
+ final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId,
+ /* includeDisabledDisplays= */ true);
if (display != null) {
final DisplayInfo info =
getDisplayInfoForFrameRateOverride(display.getFrameRateOverrides(),
@@ -2128,16 +2129,18 @@
}
void resetBrightnessConfigurations() {
- mPersistentDataStore.setBrightnessConfigurationForUser(null, mContext.getUserId(),
- mContext.getPackageName());
- mLogicalDisplayMapper.forEachLocked((logicalDisplay -> {
- if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) {
- return;
- }
- final String uniqueId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
- setBrightnessConfigurationForDisplayInternal(null, uniqueId, mContext.getUserId(),
+ synchronized (mSyncRoot) {
+ mPersistentDataStore.setBrightnessConfigurationForUser(null, mContext.getUserId(),
mContext.getPackageName());
- }));
+ mLogicalDisplayMapper.forEachLocked((logicalDisplay -> {
+ if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) {
+ return;
+ }
+ String uniqueId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
+ setBrightnessConfigurationForDisplayInternal(null, uniqueId, mContext.getUserId(),
+ mContext.getPackageName());
+ }));
+ }
}
void setAutoBrightnessLoggingEnabled(boolean enabled) {
@@ -2814,15 +2817,16 @@
}
/**
- * Returns the list of all display ids.
+ * Returns the list of all enabled display ids, and disabled ones if specified.
*/
@Override // Binder call
- public int[] getDisplayIds() {
+ public int[] getDisplayIds(boolean includeDisabledDisplays) {
final int callingUid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
- return mLogicalDisplayMapper.getDisplayIdsLocked(callingUid);
+ return mLogicalDisplayMapper.getDisplayIdsLocked(callingUid,
+ includeDisabledDisplays);
}
} finally {
Binder.restoreCallingIdentity(token);
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index a5bb716..d05a902 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -657,12 +657,6 @@
}
mIsRbcActive = mCdsi.isReduceBrightColorsActivated();
mAutomaticBrightnessController.recalculateSplines(mIsRbcActive, adjustedNits);
-
- // If rbc is turned on, off or there is a change in strength, we want to reset the short
- // term model. Since the nits range at which brightness now operates has changed due to
- // RBC/strength change, any short term model based on the previous range should be
- // invalidated.
- mAutomaticBrightnessController.resetShortTermModel();
}
/**
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 70c9e23..34e8e75 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -79,8 +79,12 @@
private static final int MSG_TRANSITION_TO_PENDING_DEVICE_STATE = 1;
private static final int UPDATE_STATE_NEW = 0;
- private static final int UPDATE_STATE_TRANSITION = 1;
- private static final int UPDATE_STATE_UPDATED = 2;
+ private static final int UPDATE_STATE_UPDATED = 1;
+ private static final int UPDATE_STATE_DISABLED = 2;
+
+ private static final int UPDATE_STATE_MASK = 0x3;
+
+ private static final int UPDATE_STATE_FLAG_TRANSITION = 0x100;
/**
* Temporary display info, used for comparing display configurations.
@@ -166,7 +170,7 @@
LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
@NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
- @NonNull Handler handler) {
+ @NonNull Handler handler, @NonNull DeviceStateToLayoutMap deviceStateToLayoutMap) {
mSyncRoot = syncRoot;
mPowerManager = context.getSystemService(PowerManager.class);
mInteractive = mPowerManager.isInteractive();
@@ -181,7 +185,7 @@
mDeviceStatesOnWhichToSleep = toSparseBooleanArray(context.getResources().getIntArray(
com.android.internal.R.array.config_deviceStatesOnWhichToSleep));
mDisplayDeviceRepo.addListener(this);
- mDeviceStateToLayoutMap = new DeviceStateToLayoutMap();
+ mDeviceStateToLayoutMap = deviceStateToLayoutMap;
}
@Override
@@ -218,10 +222,29 @@
}
public LogicalDisplay getDisplayLocked(int displayId) {
- return mLogicalDisplays.get(displayId);
+ return getDisplayLocked(displayId, /* includeDisabled= */ false);
+ }
+
+ LogicalDisplay getDisplayLocked(int displayId, boolean includeDisabled) {
+ LogicalDisplay display = mLogicalDisplays.get(displayId);
+ if (display != null && (display.isEnabled() || includeDisabled)) {
+ return display;
+ }
+ return null;
}
public LogicalDisplay getDisplayLocked(DisplayDevice device) {
+ return getDisplayLocked(device, /* includeDisabled= */ false);
+ }
+
+ /**
+ * Loops through the existing list of displays and returns one that is associated with the
+ * specified display device.
+ *
+ * @param device The display device that should be associated with the LogicalDisplay.
+ * @param includeDisabled True if this method should return disabled displays as well.
+ */
+ private LogicalDisplay getDisplayLocked(DisplayDevice device, boolean includeDisabled) {
if (device == null) {
return null;
}
@@ -229,18 +252,32 @@
for (int i = 0; i < count; i++) {
final LogicalDisplay display = mLogicalDisplays.valueAt(i);
if (display.getPrimaryDisplayDeviceLocked() == device) {
- return display;
+ if (display.isEnabled() || includeDisabled) {
+ return display;
+ } else {
+ return null;
+ }
}
}
return null;
}
+ // Returns display Ids, defaults to enabled only.
public int[] getDisplayIdsLocked(int callingUid) {
+ return getDisplayIdsLocked(callingUid, /* includeDisabledDisplays= */ false);
+ }
+
+ // Returns display Ids, specified whether enabled only, or all displays.
+ public int[] getDisplayIdsLocked(int callingUid, boolean includeDisabledDisplays) {
final int count = mLogicalDisplays.size();
int[] displayIds = new int[count];
int n = 0;
for (int i = 0; i < count; i++) {
LogicalDisplay display = mLogicalDisplays.valueAt(i);
+ if (!includeDisabledDisplays && !display.isEnabled()) {
+ continue; // Ignore disabled displays.
+ }
+
DisplayInfo info = display.getDisplayInfoLocked();
if (info.hasAccess(callingUid)) {
displayIds[n++] = mLogicalDisplays.keyAt(i);
@@ -255,7 +292,10 @@
public void forEachLocked(Consumer<LogicalDisplay> consumer) {
final int count = mLogicalDisplays.size();
for (int i = 0; i < count; i++) {
- consumer.accept(mLogicalDisplays.valueAt(i));
+ LogicalDisplay display = mLogicalDisplays.valueAt(i);
+ if (display.isEnabled()) {
+ consumer.accept(display);
+ }
}
}
@@ -316,7 +356,8 @@
// Find or create the LogicalDisplay to map the DisplayDevice to.
final int logicalDisplayId = displayLayout.getLogicalDisplayId();
- final LogicalDisplay logicalDisplay = getDisplayLocked(logicalDisplayId);
+ final LogicalDisplay logicalDisplay =
+ getDisplayLocked(logicalDisplayId, /* includeDisabled= */ true);
if (logicalDisplay == null) {
Slog.w(TAG, "The logical display (" + address + "), is not available"
+ " for the display state " + deviceState);
@@ -452,7 +493,7 @@
}
/**
- * Returns if the device should be put to sleep or not.
+ * Returns true if the device should be put to sleep or not.
*
* Includes a check to verify that the device state that we are moving to, {@code pendingState},
* is the same as the physical state of the device, {@code baseState}. Different values for
@@ -598,9 +639,12 @@
display.getNonOverrideDisplayInfoLocked(mTempNonOverrideDisplayInfo);
display.updateLocked(mDisplayDeviceRepo);
- final DisplayInfo newDisplayInfo = display.getDisplayInfoLocked();
- final int updateState = mUpdatedLogicalDisplays.get(displayId, UPDATE_STATE_NEW);
- final boolean wasPreviouslyUpdated = updateState != UPDATE_STATE_NEW;
+ DisplayInfo newDisplayInfo = display.getDisplayInfoLocked();
+
+ final int storedState = mUpdatedLogicalDisplays.get(displayId, UPDATE_STATE_NEW);
+ final int updateState = storedState & UPDATE_STATE_MASK;
+ final boolean isTransitioning = (storedState & UPDATE_STATE_FLAG_TRANSITION) != 0;
+ final boolean wasPreviouslyUpdated = updateState == UPDATE_STATE_UPDATED;
// The display is no longer valid and needs to be removed.
if (!display.isValidLocked()) {
@@ -624,6 +668,35 @@
}
continue;
+ // The display has been newly disabled, we report this as a removed display but
+ // don't actually remove it from our internal list in LogicalDisplayMapper. The reason
+ // is that LogicalDisplayMapper assumes and relies on the fact that every DisplayDevice
+ // has a LogicalDisplay wrapper, but certain displays that are unusable (like the inner
+ // display on a folded foldable device) are not available for use by the system and
+ // we keep them hidden. To do this, we mark those LogicalDisplays as "disabled".
+ // Also, if the display is in TRANSITION but was previously reported as disabled
+ // then keep it unreported.
+ } else if (!display.isEnabled()
+ || (display.getPhase() == LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION
+ && updateState == UPDATE_STATE_DISABLED)) {
+ mUpdatedLogicalDisplays.put(displayId, UPDATE_STATE_DISABLED);
+
+ // If we never told anyone about this display, nothing to do
+ if (!wasPreviouslyUpdated) {
+ continue;
+ }
+
+ // Remove from group
+ final DisplayGroup displayGroup = getDisplayGroupLocked(
+ getDisplayGroupIdFromDisplayIdLocked(displayId));
+ if (displayGroup != null) {
+ displayGroup.removeDisplayLocked(display);
+ }
+
+ Slog.i(TAG, "Removing (disabled) display: " + displayId);
+ mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_REMOVED);
+ continue;
+
// The display is new.
} else if (!wasPreviouslyUpdated) {
Slog.i(TAG, "Adding new display: " + displayId + ": " + newDisplayInfo);
@@ -643,7 +716,7 @@
mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_CHANGED);
// The display is involved in a display layout transition
- } else if (updateState == UPDATE_STATE_TRANSITION) {
+ } else if (isTransitioning) {
mLogicalDisplaysToUpdate.put(displayId,
LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION);
@@ -717,7 +790,7 @@
}
final int id = mLogicalDisplaysToUpdate.keyAt(i);
- final LogicalDisplay display = getDisplayLocked(id);
+ final LogicalDisplay display = getDisplayLocked(id, /* includeDisabled= */ true);
if (DEBUG) {
final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
final String uniqueId = device == null ? "null" : device.getUniqueId();
@@ -725,7 +798,7 @@
+ " with device=" + uniqueId);
}
mListener.onLogicalDisplayEventLocked(display, msg);
- if (msg == LOGICAL_DISPLAY_EVENT_REMOVED) {
+ if (msg == LOGICAL_DISPLAY_EVENT_REMOVED && !display.isValidLocked()) {
// We wait until we sent the EVENT_REMOVED event before actually removing the
// display.
mLogicalDisplays.delete(id);
@@ -845,7 +918,8 @@
if (isTransitioning) {
setDisplayPhase(logicalDisplay, phase);
if (phase == LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION) {
- mUpdatedLogicalDisplays.put(displayId, UPDATE_STATE_TRANSITION);
+ int oldState = mUpdatedLogicalDisplays.get(displayId, UPDATE_STATE_NEW);
+ mUpdatedLogicalDisplays.put(displayId, oldState | UPDATE_STATE_FLAG_TRANSITION);
}
}
}
@@ -879,14 +953,15 @@
// Now that we have a display-device, we need a LogicalDisplay to map it to. Find the
// right one, if it doesn't exist, create a new one.
final int logicalDisplayId = displayLayout.getLogicalDisplayId();
- LogicalDisplay newDisplay = getDisplayLocked(logicalDisplayId);
+ LogicalDisplay newDisplay =
+ getDisplayLocked(logicalDisplayId, /* includeDisabled= */ true);
if (newDisplay == null) {
newDisplay = createNewLogicalDisplayLocked(
- null /*displayDevice*/, logicalDisplayId);
+ /* displayDevice= */ null, logicalDisplayId);
}
// Now swap the underlying display devices between the old display and the new display
- final LogicalDisplay oldDisplay = getDisplayLocked(device);
+ final LogicalDisplay oldDisplay = getDisplayLocked(device, /* includeDisabled= */ true);
if (newDisplay != oldDisplay) {
newDisplay.swapDisplaysLocked(oldDisplay);
}
@@ -903,13 +978,14 @@
* Creates a new logical display for the specified device and display Id and adds it to the list
* of logical displays.
*
- * @param device The device to associate with the LogicalDisplay.
+ * @param displayDevice The displayDevice to associate with the LogicalDisplay.
* @param displayId The display ID to give the new display. If invalid, a new ID is assigned.
* @return The new logical display if created, null otherwise.
*/
- private LogicalDisplay createNewLogicalDisplayLocked(DisplayDevice device, int displayId) {
+ private LogicalDisplay createNewLogicalDisplayLocked(DisplayDevice displayDevice,
+ int displayId) {
final int layerStack = assignLayerStackLocked(displayId);
- final LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
+ final LogicalDisplay display = new LogicalDisplay(displayId, layerStack, displayDevice);
display.updateLocked(mDisplayDeviceRepo);
mLogicalDisplays.put(displayId, display);
setDisplayPhase(display, LogicalDisplay.DISPLAY_PHASE_ENABLED);
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
index 59daee9..b9a0738 100644
--- a/services/core/java/com/android/server/display/PersistentDataStore.java
+++ b/services/core/java/com/android/server/display/PersistentDataStore.java
@@ -153,7 +153,7 @@
@VisibleForTesting
PersistentDataStore(Injector injector) {
- this(injector, BackgroundThread.getHandler());
+ this(injector, new Handler(BackgroundThread.getHandler().getLooper()));
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index d536a46..b89147e 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -563,14 +563,16 @@
try {
enforcePackageName(callingPackage, callingUid);
if (targetUid != callingUid) {
- Log.d(TAG, "tempAllowlistTargetPkgIfPossible callingPackage:"
- + callingPackage + " targetPackage:" + targetPackage
- + " reason:" + reason);
boolean canAllowWhileInUse = mActivityManagerLocal
.canAllowWhileInUsePermissionInFgs(callingPid, callingUid, callingPackage);
boolean canStartFgs = canAllowWhileInUse
|| mActivityManagerLocal.canStartForegroundService(callingPid, callingUid,
callingPackage);
+ Log.i(TAG, "tempAllowlistTargetPkgIfPossible callingPackage:"
+ + callingPackage + " targetPackage:" + targetPackage
+ + " reason:" + reason
+ + (canAllowWhileInUse ? " [WIU]" : "")
+ + (canStartFgs ? " [FGS]" : ""));
if (canAllowWhileInUse) {
mActivityManagerLocal.tempAllowWhileInUsePermissionInFgs(targetUid,
MediaSessionDeviceConfig
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
index 67aed45..3cd7795 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
@@ -317,7 +317,7 @@
mEnforcer.assertApprovedVerifier(callingUid, mProxy);
final Computer snapshot = mConnection.snapshot();
synchronized (mLock) {
- List<String> verifiedDomains = new ArrayList<>();
+ List<String> newlyVerifiedDomains = new ArrayList<>();
GetAttachedResult result = getAndValidateAttachedLocked(domainSetId, domains,
true /* forAutoVerify */, callingUid, null /* userId */, snapshot);
@@ -329,21 +329,28 @@
ArrayMap<String, Integer> stateMap = pkgState.getStateMap();
for (String domain : domains) {
Integer previousState = stateMap.get(domain);
- if (previousState != null
- && !DomainVerificationState.isModifiable(previousState)) {
- continue;
+ // Skip if the state hasn't changed or can't be changed
+ if (previousState != null) {
+ if (previousState == state
+ || !DomainVerificationState.isModifiable(previousState)) {
+ continue;
+ }
}
if (DomainVerificationState.isVerified(state)) {
- verifiedDomains.add(domain);
+ if (previousState == null
+ || !DomainVerificationState.isVerified(previousState)) {
+ newlyVerifiedDomains.add(domain);
+ }
}
stateMap.put(domain, state);
}
- int size = verifiedDomains.size();
+ // For newly verified domains, revoke their user states across other packages
+ int size = newlyVerifiedDomains.size();
for (int index = 0; index < size; index++) {
- removeUserStatesForDomain(verifiedDomains.get(index));
+ removeUserStatesForDomain(pkgState, newlyVerifiedDomains.get(index));
}
}
@@ -367,7 +374,6 @@
"State must be one of NO_RESPONSE, SUCCESS, APPROVED, or DENIED");
}
- ArraySet<String> verifiedDomains = new ArraySet<>();
if (packageName == null) {
final Computer snapshot = mConnection.snapshot();
synchronized (mLock) {
@@ -395,10 +401,6 @@
validDomains.retainAll(autoVerifyDomains);
}
- if (DomainVerificationState.isVerified(state)) {
- verifiedDomains.addAll(validDomains);
- }
-
setDomainVerificationStatusInternal(pkgState, state, validDomains);
}
}
@@ -424,19 +426,33 @@
validDomains.retainAll(mCollector.collectValidAutoVerifyDomains(pkg));
}
+ ArraySet<String> newlyVerifiedDomains = null;
if (DomainVerificationState.isVerified(state)) {
- verifiedDomains.addAll(validDomains);
+ newlyVerifiedDomains = new ArraySet<>();
+ ArrayMap<String, Integer> stateMap = pkgState.getStateMap();
+ int domainsSize = validDomains.size();
+ for (int domainIndex = 0; domainIndex < domainsSize; domainIndex++) {
+ String domain = validDomains.valueAt(domainIndex);
+ Integer oldState = stateMap.get(domain);
+ // Only remove if not previously verified
+ if (oldState == null || !DomainVerificationState.isVerified(oldState)) {
+ newlyVerifiedDomains.add(domain);
+ }
+ }
}
setDomainVerificationStatusInternal(pkgState, state, validDomains);
- }
- }
- // Mirror SystemApi behavior of revoking user selection for approved domains.
- if (DomainVerificationState.isVerified(state)) {
- final int size = verifiedDomains.size();
- for (int index = 0; index < size; index++) {
- removeUserStatesForDomain(verifiedDomains.valueAt(index));
+ // Mirror SystemApi behavior of revoking user selection for approved domains.
+ // This is done in a second pass so that the previous state can be compared before
+ // the previous method overwrites it with the new state.
+ if (newlyVerifiedDomains != null) {
+ int domainsSize = newlyVerifiedDomains.size();
+ for (int domainIndex = 0; domainIndex < domainsSize; domainIndex++) {
+ String domain = newlyVerifiedDomains.valueAt(domainIndex);
+ removeUserStatesForDomain(pkgState, domain);
+ }
+ }
}
}
@@ -452,7 +468,10 @@
}
}
- private void removeUserStatesForDomain(@NonNull String domain) {
+ private void removeUserStatesForDomain(@NonNull DomainVerificationPkgState owningPkgState,
+ @NonNull String domain) {
+ SparseArray<DomainVerificationInternalUserState> owningUserStates =
+ owningPkgState.getUserStates();
synchronized (mLock) {
final int size = mAttachedPkgStates.size();
for (int index = 0; index < size; index++) {
@@ -460,6 +479,15 @@
SparseArray<DomainVerificationInternalUserState> array = pkgState.getUserStates();
int arraySize = array.size();
for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) {
+ int userId = array.keyAt(arrayIndex);
+ DomainVerificationInternalUserState owningUserState =
+ owningUserStates.get(userId);
+ if (owningUserState != null && !owningUserState.isLinkHandlingAllowed()) {
+ // Skip users where the owning package has their link handling disabled,
+ // since revoking those users would lead to no apps being able to handle
+ // the domain.
+ continue;
+ }
array.valueAt(arrayIndex).removeHost(domain);
}
}
@@ -527,6 +555,8 @@
mConnection.scheduleWriteSettings();
}
+ @CheckResult
+ @DomainVerificationManager.Error
public int setDomainVerificationUserSelection(@NonNull UUID domainSetId,
@NonNull Set<String> domains, boolean enabled, @UserIdInt int userId)
throws NameNotFoundException {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 859b4df..5c473d8 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -432,6 +432,7 @@
private static final int DESTROY_TIMEOUT = 10 * 1000;
final ActivityTaskManagerService mAtmService;
+ @NonNull
final ActivityInfo info; // activity info provided by developer in AndroidManifest
// Which user is this running for?
final int mUserId;
@@ -4299,9 +4300,15 @@
mTransitionController.collect(tStartingWindow);
tStartingWindow.reparent(this, POSITION_TOP);
- // Propagate other interesting state between the tokens. If the old token is displayed,
- // we should immediately force the new one to be displayed. If it is animating, we need
- // to move that animation to the new one.
+ // Clear the frozen insets state when transferring the existing starting window to
+ // the next target activity. In case the frozen state from a trampoline activity
+ // affecting the starting window frame computation to see the window being
+ // clipped if the rotation change during the transition animation.
+ tStartingWindow.clearFrozenInsetsState();
+
+ // Propagate other interesting state between the tokens. If the old token is
+ // displayed, we should immediately force the new one to be displayed. If it is
+ // animating, we need to move that animation to the new one.
if (fromActivity.allDrawn) {
allDrawn = true;
}
@@ -9707,6 +9714,15 @@
return true;
}
+ @Nullable
+ Point getMinDimensions() {
+ final ActivityInfo.WindowLayout windowLayout = info.windowLayout;
+ if (windowLayout == null) {
+ return null;
+ }
+ return new Point(windowLayout.minWidth, windowLayout.minHeight);
+ }
+
static class Builder {
private final ActivityTaskManagerService mAtmService;
private WindowProcessController mCallerApp;
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index d60981f..32ed472 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -508,7 +508,8 @@
*/
int startActivityInTaskFragment(@NonNull TaskFragment taskFragment,
@NonNull Intent activityIntent, @Nullable Bundle activityOptions,
- @Nullable IBinder resultTo, int callingUid, int callingPid) {
+ @Nullable IBinder resultTo, int callingUid, int callingPid,
+ @Nullable IBinder errorCallbackToken) {
final ActivityRecord caller =
resultTo != null ? ActivityRecord.forTokenLocked(resultTo) : null;
return obtainStarter(activityIntent, "startActivityInTaskFragment")
@@ -521,6 +522,7 @@
.setRealCallingUid(callingUid)
.setRealCallingPid(callingPid)
.setUserId(caller != null ? caller.mUserId : mService.getCurrentUserId())
+ .setErrorCallbackToken(errorCallbackToken)
.execute();
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index fb87576..84cd634 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -89,7 +89,6 @@
import android.app.ProfilerInfo;
import android.app.WaitResult;
import android.app.WindowConfiguration;
-import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.content.ComponentName;
@@ -369,6 +368,13 @@
int filterCallingUid;
PendingIntentRecord originatingPendingIntent;
boolean allowBackgroundActivityStart;
+ /**
+ * The error callback token passed in {@link android.window.WindowContainerTransaction}
+ * for TaskFragment operation error handling via
+ * {@link android.window.TaskFragmentOrganizer#onTaskFragmentError(IBinder, Throwable)}.
+ */
+ @Nullable
+ IBinder errorCallbackToken;
/**
* If set to {@code true}, allows this activity start to look into
@@ -422,6 +428,7 @@
filterCallingUid = UserHandle.USER_NULL;
originatingPendingIntent = null;
allowBackgroundActivityStart = false;
+ errorCallbackToken = null;
}
/**
@@ -464,6 +471,7 @@
filterCallingUid = request.filterCallingUid;
originatingPendingIntent = request.originatingPendingIntent;
allowBackgroundActivityStart = request.allowBackgroundActivityStart;
+ errorCallbackToken = request.errorCallbackToken;
}
/**
@@ -2889,6 +2897,7 @@
private void addOrReparentStartingActivity(@NonNull Task task, String reason) {
TaskFragment newParent = task;
if (mInTaskFragment != null) {
+ // TODO(b/234351413): remove remaining embedded Task logic.
// mInTaskFragment is created and added to the leaf task by task fragment organizer's
// request. If the task was resolved and different than mInTaskFragment, reparent the
// task to mInTaskFragment for embedding.
@@ -2915,7 +2924,14 @@
newParent = candidateTf;
}
}
-
+ // Start Activity to the Task if mStartActivity's min dimensions are not satisfied.
+ if (newParent.isEmbedded() && newParent.smallerThanMinDimension(mStartActivity)) {
+ reason += " - MinimumDimensionViolation";
+ mService.mWindowOrganizerController.sendMinimumDimensionViolation(
+ newParent, mStartActivity.getMinDimensions(), mRequest.errorCallbackToken,
+ reason);
+ newParent = task;
+ }
if (mStartActivity.getTaskFragment() == null
|| mStartActivity.getTaskFragment() == newParent) {
newParent.addChild(mStartActivity, POSITION_TOP);
@@ -3200,6 +3216,11 @@
return this;
}
+ ActivityStarter setErrorCallbackToken(@Nullable IBinder errorCallbackToken) {
+ mRequest.errorCallbackToken = errorCallbackToken;
+ return this;
+ }
+
void dump(PrintWriter pw, String prefix) {
pw.print(prefix);
pw.print("mCurrentUser=");
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index eca0fd7..1d32867 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -152,6 +152,7 @@
final RootWindowContainer mRootWindowContainer;
private final TaskFragmentOrganizerController mTaskFragmentOrganizerController;
+ // TODO(b/233177466): Move mMinWidth and mMinHeight to Task and remove usages in TaskFragment
/**
* Minimal width of this task fragment when it's resizeable. {@link #INVALID_MIN_SIZE} means it
* should use the default minimal width.
@@ -535,6 +536,25 @@
|| isAllowedToEmbedActivityInTrustedMode(a, uid);
}
+ boolean smallerThanMinDimension(@NonNull ActivityRecord activity) {
+ final Rect taskFragBounds = getBounds();
+ final Task task = getTask();
+ // Don't need to check if the bounds match parent Task bounds because the fallback mechanism
+ // is to reparent the Activity to parent if minimum dimensions are not satisfied.
+ if (task == null || taskFragBounds.equals(task.getBounds())) {
+ return false;
+ }
+ final Point minDimensions = activity.getMinDimensions();
+ if (minDimensions == null) {
+ return false;
+ }
+ final int minWidth = minDimensions.x;
+ final int minHeight = minDimensions.y;
+ final boolean smaller = taskFragBounds.width() < minWidth
+ || taskFragBounds.height() < minHeight;
+ return smaller;
+ }
+
/**
* Checks if the organized task fragment is allowed to embed activity in untrusted mode.
*/
@@ -1755,7 +1775,8 @@
mClearedTaskForReuse = false;
mClearedTaskFragmentForPip = false;
- boolean isAddingActivity = child.asActivityRecord() != null;
+ final ActivityRecord addingActivity = child.asActivityRecord();
+ final boolean isAddingActivity = addingActivity != null;
final Task task = isAddingActivity ? getTask() : null;
// If this task had any activity before we added this one.
@@ -1780,7 +1801,7 @@
mBackScreenshots.put(r.mActivityComponent.flattenToString(), backBuffer);
}
child.asActivityRecord().inHistory = true;
- task.onDescendantActivityAdded(taskHadActivity, activityType, child.asActivityRecord());
+ task.onDescendantActivityAdded(taskHadActivity, activityType, addingActivity);
}
}
@@ -2294,7 +2315,7 @@
TaskFragmentInfo getTaskFragmentInfo() {
List<IBinder> childActivities = new ArrayList<>();
for (int i = 0; i < getChildCount(); i++) {
- final WindowContainer wc = getChildAt(i);
+ final WindowContainer<?> wc = getChildAt(i);
final ActivityRecord ar = wc.asActivityRecord();
if (mTaskFragmentOrganizerUid != INVALID_UID && ar != null
&& ar.info.processName.equals(mTaskFragmentOrganizerProcessName)
@@ -2314,7 +2335,31 @@
childActivities,
positionInParent,
mClearedTaskForReuse,
- mClearedTaskFragmentForPip);
+ mClearedTaskFragmentForPip,
+ calculateMinDimension());
+ }
+
+ /**
+ * Calculates the minimum dimensions that this TaskFragment can be resized.
+ * @see TaskFragmentInfo#getMinimumWidth()
+ * @see TaskFragmentInfo#getMinimumHeight()
+ */
+ Point calculateMinDimension() {
+ final int[] maxMinWidth = new int[1];
+ final int[] maxMinHeight = new int[1];
+
+ forAllActivities(a -> {
+ if (a.finishing) {
+ return;
+ }
+ final Point minDimensions = a.getMinDimensions();
+ if (minDimensions == null) {
+ return;
+ }
+ maxMinWidth[0] = Math.max(maxMinWidth[0], minDimensions.x);
+ maxMinHeight[0] = Math.max(maxMinHeight[0], minDimensions.y);
+ });
+ return new Point(maxMinWidth[0], maxMinHeight[0]);
}
@Nullable
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index ff3b4a5..22d6237 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.isStartResultSuccessful;
+import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_ADD_RECT_INSETS_PROVIDER;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT;
@@ -56,6 +57,7 @@
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
+import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Bundle;
@@ -115,7 +117,7 @@
static final int CONTROLLABLE_CONFIGS = ActivityInfo.CONFIG_WINDOW_CONFIGURATION
| ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE | ActivityInfo.CONFIG_SCREEN_SIZE
| ActivityInfo.CONFIG_LAYOUT_DIRECTION;
- static final int CONTROLLABLE_WINDOW_CONFIGS = WindowConfiguration.WINDOW_CONFIG_BOUNDS
+ static final int CONTROLLABLE_WINDOW_CONFIGS = WINDOW_CONFIG_BOUNDS
| WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS;
private final ActivityTaskManagerService mService;
@@ -421,7 +423,8 @@
}
}
- int containerEffect = applyWindowContainerChange(wc, entry.getValue());
+ int containerEffect = applyWindowContainerChange(wc, entry.getValue(),
+ t.getErrorCallbackToken());
effects |= containerEffect;
// Lifecycle changes will trigger ensureConfig for everything.
@@ -503,7 +506,8 @@
}
}
- private int applyChanges(WindowContainer container, WindowContainerTransaction.Change change) {
+ private int applyChanges(WindowContainer<?> container,
+ WindowContainerTransaction.Change change, @Nullable IBinder errorCallbackToken) {
// The "client"-facing API should prevent bad changes; however, just in case, sanitize
// masks here.
final int configMask = change.getConfigSetMask() & CONTROLLABLE_CONFIGS;
@@ -511,6 +515,9 @@
int effects = 0;
final int windowingMode = change.getWindowingMode();
if (configMask != 0) {
+
+ adjustBoundsForMinDimensionsIfNeeded(container, change, errorCallbackToken);
+
if (windowingMode > -1 && windowingMode != container.getWindowingMode()) {
// Special handling for when we are setting a windowingMode in the same transaction.
// Setting the windowingMode is going to call onConfigurationChanged so we don't
@@ -556,6 +563,26 @@
return effects;
}
+ private void adjustBoundsForMinDimensionsIfNeeded(WindowContainer<?> container,
+ WindowContainerTransaction.Change change, @Nullable IBinder errorCallbackToken) {
+ final TaskFragment taskFragment = container.asTaskFragment();
+ if (taskFragment == null || !taskFragment.isEmbedded()) {
+ return;
+ }
+ if ((change.getWindowSetMask() & WINDOW_CONFIG_BOUNDS) == 0) {
+ return;
+ }
+ final WindowConfiguration winConfig = change.getConfiguration().windowConfiguration;
+ final Rect bounds = winConfig.getBounds();
+ final Point minDimensions = taskFragment.calculateMinDimension();
+ if (bounds.width() < minDimensions.x || bounds.height() < minDimensions.y) {
+ sendMinimumDimensionViolation(taskFragment, minDimensions, errorCallbackToken,
+ "setBounds:" + bounds);
+ // Sets the bounds to match parent bounds.
+ winConfig.setBounds(new Rect());
+ }
+ }
+
private int applyTaskChanges(Task tr, WindowContainerTransaction.Change c) {
int effects = 0;
final SurfaceControl.Transaction t = c.getBoundsChangeTransaction();
@@ -696,7 +723,8 @@
final Bundle activityOptions = hop.getLaunchOptions();
final int result = mService.getActivityStartController()
.startActivityInTaskFragment(tf, activityIntent, activityOptions,
- hop.getCallingActivity(), caller.mUid, caller.mPid);
+ hop.getCallingActivity(), caller.mUid, caller.mPid,
+ errorCallbackToken);
if (!isStartResultSuccessful(result)) {
sendTaskFragmentOperationFailure(organizer, errorCallbackToken,
convertStartFailureToThrowable(result, activityIntent));
@@ -740,6 +768,12 @@
sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception);
break;
}
+ if (parent.smallerThanMinDimension(activity)) {
+ sendMinimumDimensionViolation(parent, activity.getMinDimensions(),
+ errorCallbackToken, "reparentActivityToTask");
+ break;
+ }
+
activity.reparent(parent, POSITION_TOP);
effects |= TRANSACT_EFFECTS_LIFECYCLE;
break;
@@ -953,6 +987,19 @@
return effects;
}
+ /** A helper method to send minimum dimension violation error to the client. */
+ void sendMinimumDimensionViolation(TaskFragment taskFragment, Point minDimensions,
+ IBinder errorCallbackToken, String reason) {
+ if (taskFragment == null || taskFragment.getTaskFragmentOrganizer() == null) {
+ return;
+ }
+ final Throwable exception = new SecurityException("The task fragment's bounds:"
+ + taskFragment.getBounds() + " does not satisfy minimum dimensions:"
+ + minDimensions + " " + reason);
+ sendTaskFragmentOperationFailure(taskFragment.getTaskFragmentOrganizer(),
+ errorCallbackToken, exception);
+ }
+
/**
* Post and wait for the result of the activity start to prevent potential deadlock against
* {@link WindowManagerGlobalLock}.
@@ -1164,14 +1211,14 @@
}
private int applyWindowContainerChange(WindowContainer wc,
- WindowContainerTransaction.Change c) {
+ WindowContainerTransaction.Change c, @Nullable IBinder errorCallbackToken) {
sanitizeWindowContainer(wc);
if (wc.asTaskFragment() != null && wc.asTaskFragment().isEmbeddedTaskFragmentInPip()) {
// No override from organizer for embedded TaskFragment in a PIP Task.
return 0;
}
- int effects = applyChanges(wc, c);
+ int effects = applyChanges(wc, c, errorCallbackToken);
if (wc instanceof DisplayArea) {
effects |= applyDisplayAreaChanges(wc.asDisplayArea(), c);
@@ -1515,8 +1562,9 @@
mLaunchTaskFragments.put(creationParams.getFragmentToken(), taskFragment);
}
- void reparentTaskFragment(@NonNull TaskFragment oldParent, @Nullable WindowContainer newParent,
- @Nullable ITaskFragmentOrganizer organizer, @Nullable IBinder errorCallbackToken) {
+ void reparentTaskFragment(@NonNull TaskFragment oldParent,
+ @Nullable WindowContainer<?> newParent, @Nullable ITaskFragmentOrganizer organizer,
+ @Nullable IBinder errorCallbackToken) {
final TaskFragment newParentTF;
if (newParent == null) {
// Use the old parent's parent if the caller doesn't specify the new parent.
@@ -1554,6 +1602,14 @@
sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception);
return;
}
+ final Point minDimensions = oldParent.calculateMinDimension();
+ final Rect newParentBounds = newParentTF.getBounds();
+ if (newParentBounds.width() < minDimensions.x
+ || newParentBounds.height() < minDimensions.y) {
+ sendMinimumDimensionViolation(newParentTF, minDimensions, errorCallbackToken,
+ "reparentTaskFragment");
+ return;
+ }
while (oldParent.hasChild()) {
oldParent.getChildAt(0).reparent(newParentTF, POSITION_TOP);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index cb78ad8..590de7b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -9292,11 +9292,11 @@
}
// Check profile owner first as that is what most likely is set.
- if (isSupervisionComponent(poComponent)) {
+ if (isSupervisionComponentLocked(poComponent)) {
return poComponent;
}
- if (isSupervisionComponent(doComponent)) {
+ if (isSupervisionComponentLocked(doComponent)) {
return doComponent;
}
@@ -9304,7 +9304,26 @@
}
}
- private boolean isSupervisionComponent(@Nullable ComponentName who) {
+ /**
+ * Returns if the specified component is the supervision component.
+ */
+ @Override
+ public boolean isSupervisionComponent(@NonNull ComponentName who) {
+ if (!mHasFeature) {
+ return false;
+ }
+ synchronized (getLockObject()) {
+ if (mConstants.USE_TEST_ADMIN_AS_SUPERVISION_COMPONENT) {
+ final CallerIdentity caller = getCallerIdentity();
+ if (isAdminTestOnlyLocked(who, caller.getUserId())) {
+ return true;
+ }
+ }
+ return isSupervisionComponentLocked(who);
+ }
+ }
+
+ private boolean isSupervisionComponentLocked(@Nullable ComponentName who) {
if (who == null) {
return false;
}
@@ -9508,7 +9527,7 @@
"Cannot set the profile owner on a user which is already set-up");
if (!mIsWatch) {
- if (!isSupervisionComponent(owner)) {
+ if (!isSupervisionComponentLocked(owner)) {
throw new IllegalStateException("Unable to set non-default profile owner"
+ " post-setup " + owner);
}
@@ -12102,8 +12121,8 @@
synchronized (getLockObject()) {
// Allow testOnly admins to bypass supervision config requirement.
Preconditions.checkCallAuthorization(isAdminTestOnlyLocked(who, caller.getUserId())
- || isSupervisionComponent(caller.getComponentName()), "Admin %s is not the "
- + "default supervision component", caller.getComponentName());
+ || isSupervisionComponentLocked(caller.getComponentName()), "Admin %s is not "
+ + "the default supervision component", caller.getComponentName());
DevicePolicyData policy = getUserData(caller.getUserId());
policy.mSecondaryLockscreenEnabled = enabled;
saveSettingsLocked(caller.getUserId());
@@ -13004,7 +13023,7 @@
return false;
}
- return isSupervisionComponent(admin.info.getComponent());
+ return isSupervisionComponentLocked(admin.info.getComponent());
}
}
diff --git a/services/proguard.flags b/services/proguard.flags
index bad02b4..c648f7d 100644
--- a/services/proguard.flags
+++ b/services/proguard.flags
@@ -68,6 +68,9 @@
# TODO(b/210510433): Revisit and consider generating from frameworks/base/core/res/res/values/config.xml.
-keep,allowoptimization,allowaccessmodification public class com.android.server.notification.** implements com.android.server.notification.NotificationSignalExtractor
+# OEM provided DisplayAreaPolicy.Provider defined in frameworks/base/core/res/res/values/config.xml.
+-keep,allowoptimization,allowaccessmodification class com.android.server.wm.** implements com.android.server.wm.DisplayAreaPolicy$Provider
+
# JNI keep rules
# TODO(b/210510433): Revisit and fix with @Keep, or consider auto-generating from
# frameworks/base/services/core/jni/onload.cpp.
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
index 40f37a7..ed60c50 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
@@ -78,6 +78,8 @@
private val DOMAIN_4 = "four.$DOMAIN_BASE"
private const val USER_ID = 0
+ private const val USER_ID_SECONDARY = 10
+ private val USER_IDS = listOf(USER_ID, USER_ID_SECONDARY)
}
private val pkg1 = mockPkgState(PKG_ONE, UUID_ONE, SIGNATURE_ONE)
@@ -813,6 +815,173 @@
assertExpectedState(serviceAfter)
}
+ @Test
+ fun verifiedUnapproved_unverifiedSelected_approvalCausesUnselect_systemApi() {
+ verifiedUnapproved_unverifiedSelected_approvalCausesUnselect {
+ setDomainVerificationStatus(it.domainSetId, setOf(DOMAIN_1, DOMAIN_2), STATE_SUCCESS)
+ }
+ }
+
+ @Test
+ fun verifiedUnapproved_unverifiedSelected_approvalCausesUnselect_internalApi() {
+ verifiedUnapproved_unverifiedSelected_approvalCausesUnselect {
+ setDomainVerificationStatusInternal(it.packageName, STATE_SUCCESS,
+ ArraySet(setOf(DOMAIN_1, DOMAIN_2)))
+ }
+ }
+
+ private fun verifiedUnapproved_unverifiedSelected_approvalCausesUnselect(
+ setStatusBlock: DomainVerificationService.(PackageStateInternal) -> Unit
+ ) {
+ /*
+ Domains tested:
+ 1: Becomes verified in package 1, but package 1 disabled in secondary user, only
+ disables selection for package 2 in main user
+ 2: Becomes verified in package 1, unselected by package 2, remains unselected
+ 3: Is autoVerify, but unverified, selected by package 2, remains selected
+ 4: Non-autoVerify, selected by package 2, remains selected
+ */
+
+ val pkg1 = mockPkgState(
+ PKG_ONE,
+ UUID_ONE,
+ SIGNATURE_ONE,
+ autoVerifyDomains = listOf(DOMAIN_1, DOMAIN_2, DOMAIN_3),
+ otherDomains = listOf(DOMAIN_4)
+ )
+ val pkg2 = mockPkgState(
+ PKG_TWO,
+ UUID_TWO,
+ SIGNATURE_TWO,
+ autoVerifyDomains = emptyList(),
+ otherDomains = listOf(DOMAIN_1, DOMAIN_2, DOMAIN_3, DOMAIN_4)
+ )
+
+ val service = makeService(pkg1, pkg2)
+ service.addPackage(pkg1)
+ service.addPackage(pkg2)
+
+ // Approve domain 1, 3, and 4 for package 2 for both users
+ USER_IDS.forEach {
+ assertThat(
+ service.setDomainVerificationUserSelection(
+ UUID_TWO,
+ setOf(DOMAIN_1, DOMAIN_3, DOMAIN_4),
+ true,
+ it
+ )
+ ).isEqualTo(DomainVerificationManager.STATUS_OK)
+ }
+
+ // But disable the owner package link handling in the secondary user
+ service.setDomainVerificationLinkHandlingAllowed(pkg1.packageName, false,
+ USER_ID_SECONDARY
+ )
+
+ service.assertState(
+ pkg1,
+ verifyState = listOf(
+ DOMAIN_1 to STATE_NO_RESPONSE,
+ DOMAIN_2 to STATE_NO_RESPONSE,
+ DOMAIN_3 to STATE_NO_RESPONSE,
+ ),
+ userState2LinkHandlingAllowed = false
+ )
+
+ service.assertState(
+ pkg2,
+ verifyState = null,
+ userState1DomainState1 = DOMAIN_STATE_SELECTED,
+ userState1DomainState3 = DOMAIN_STATE_SELECTED,
+ userState1DomainState4 = DOMAIN_STATE_SELECTED,
+ userState2DomainState1 = DOMAIN_STATE_SELECTED,
+ userState2DomainState3 = DOMAIN_STATE_SELECTED,
+ userState2DomainState4 = DOMAIN_STATE_SELECTED,
+ )
+
+ // Verify the owner package
+ service.setStatusBlock(pkg1)
+
+ // Assert that package 1 is now verified, but link handling disabled in secondary user
+ service.assertState(
+ pkg1,
+ verifyState = listOf(
+ DOMAIN_1 to STATE_SUCCESS,
+ DOMAIN_2 to STATE_SUCCESS,
+ DOMAIN_3 to STATE_NO_RESPONSE,
+ ),
+ userState1DomainState1 = DOMAIN_STATE_VERIFIED,
+ userState1DomainState2 = DOMAIN_STATE_VERIFIED,
+ userState1DomainState3 = DOMAIN_STATE_NONE,
+ userState1DomainState4 = DOMAIN_STATE_NONE,
+ userState2LinkHandlingAllowed = false,
+ userState2DomainState1 = DOMAIN_STATE_VERIFIED,
+ userState2DomainState2 = DOMAIN_STATE_VERIFIED,
+ userState2DomainState3 = DOMAIN_STATE_NONE,
+ userState2DomainState4 = DOMAIN_STATE_NONE,
+ )
+
+ // Assert package 2 maintains selected in user where package 1 had link handling disabled
+ service.assertState(
+ pkg2,
+ verifyState = null,
+ userState1DomainState1 = DOMAIN_STATE_NONE,
+ userState1DomainState3 = DOMAIN_STATE_SELECTED,
+ userState1DomainState4 = DOMAIN_STATE_SELECTED,
+ userState2DomainState1 = DOMAIN_STATE_SELECTED,
+ userState2DomainState3 = DOMAIN_STATE_SELECTED,
+ userState2DomainState4 = DOMAIN_STATE_SELECTED,
+ )
+ }
+
+ fun DomainVerificationService.assertState(
+ pkg: PackageStateInternal,
+ verifyState: List<Pair<String, Int>>?,
+ userState1LinkHandlingAllowed: Boolean = true,
+ userState1DomainState1: Int = DOMAIN_STATE_NONE,
+ userState1DomainState2: Int = DOMAIN_STATE_NONE,
+ userState1DomainState3: Int = DOMAIN_STATE_NONE,
+ userState1DomainState4: Int = DOMAIN_STATE_NONE,
+ userState2LinkHandlingAllowed: Boolean = true,
+ userState2DomainState1: Int = DOMAIN_STATE_NONE,
+ userState2DomainState2: Int = DOMAIN_STATE_NONE,
+ userState2DomainState3: Int = DOMAIN_STATE_NONE,
+ userState2DomainState4: Int = DOMAIN_STATE_NONE,
+ ) {
+ if (verifyState == null) {
+ // If no auto verify domains, the info itself will be null
+ assertThat(getDomainVerificationInfo(pkg.packageName)).isNull()
+ } else {
+ getInfo(pkg.packageName).run {
+ assertThat(hostToStateMap).containsExactlyEntriesIn(verifyState.associate { it })
+ }
+ }
+
+ getUserState(pkg.packageName, USER_ID).run {
+ assertThat(isLinkHandlingAllowed).isEqualTo(userState1LinkHandlingAllowed)
+ assertThat(hostToStateMap).containsExactlyEntriesIn(
+ mapOf(
+ DOMAIN_1 to userState1DomainState1,
+ DOMAIN_2 to userState1DomainState2,
+ DOMAIN_3 to userState1DomainState3,
+ DOMAIN_4 to userState1DomainState4,
+ )
+ )
+ }
+
+ getUserState(pkg.packageName, USER_ID_SECONDARY).run {
+ assertThat(isLinkHandlingAllowed).isEqualTo(userState2LinkHandlingAllowed)
+ assertThat(hostToStateMap).containsExactlyEntriesIn(
+ mapOf(
+ DOMAIN_1 to userState2DomainState1,
+ DOMAIN_2 to userState2DomainState2,
+ DOMAIN_3 to userState2DomainState3,
+ DOMAIN_4 to userState2DomainState4,
+ )
+ )
+ }
+ }
+
private fun DomainVerificationService.getInfo(pkgName: String) =
getDomainVerificationInfo(pkgName)
.also { assertThat(it).isNotNull() }!!
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 8014d25..388170b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -3360,9 +3360,11 @@
assertThat(dpmi.isActiveSupervisionApp(uid)).isTrue();
assertThat(dpm.getProfileOwnerOrDeviceOwnerSupervisionComponent(user))
.isEqualTo(admin1);
+ assertThat(dpm.isSupervisionComponent(admin1)).isTrue();
} else {
assertThat(dpmi.isActiveSupervisionApp(uid)).isFalse();
assertThat(dpm.getProfileOwnerOrDeviceOwnerSupervisionComponent(user)).isNull();
+ assertThat(dpm.isSupervisionComponent(admin1)).isFalse();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index b0c52f1..9d82f1a 100644
--- a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -24,6 +24,7 @@
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyFloat;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -258,29 +259,36 @@
@Test
public void testRecalculateSplines() throws Exception {
// Enabling the light sensor, and setting the ambient lux to 1000
+ int currentLux = 1000;
ArgumentCaptor<SensorEventListener> listenerCaptor =
ArgumentCaptor.forClass(SensorEventListener.class);
verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor),
eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class));
SensorEventListener listener = listenerCaptor.getValue();
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1000));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, currentLux));
- //Setting the brightnessFloat to 0.5f
- float currentBrightnessFloat = 0.5f;
- when(mBrightnessMappingStrategy.getBrightness(1000,
- null, ApplicationInfo.CATEGORY_UNDEFINED)).thenReturn(currentBrightnessFloat);
+ // User sets brightness to 0.5f
+ when(mBrightnessMappingStrategy.getBrightness(currentLux,
+ null, ApplicationInfo.CATEGORY_UNDEFINED)).thenReturn(0.5f);
mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration */,
- currentBrightnessFloat /* brightness */, false /* userChangedBrightness */,
- 0 /* adjustment */, false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);
+ 0.5f /* brightness */, true /* userChangedBrightness */, 0 /* adjustment */,
+ false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);
- // Adjusting spline, and accordingly remapping the current 0.5f brightnessFloat to 0.3f
- float updatedBrightnessFloat = 0.3f;
- when(mBrightnessMappingStrategy.getBrightness(1000,
- null, ApplicationInfo.CATEGORY_UNDEFINED)).thenReturn(updatedBrightnessFloat);
- float[] adjustments = new float[]{0.2f, 0.5f};
+ //Recalculating the spline with RBC enabled, verifying that the short term model is reset,
+ //and the interaction is learnt in short term model
+ float[] adjustments = new float[]{0.2f, 0.6f};
mController.recalculateSplines(true, adjustments);
+ verify(mBrightnessMappingStrategy).clearUserDataPoints();
verify(mBrightnessMappingStrategy).recalculateSplines(true, adjustments);
- assertEquals(mController.getAutomaticScreenBrightness(), updatedBrightnessFloat, EPSILON);
+ verify(mBrightnessMappingStrategy, times(2)).addUserDataPoint(currentLux, 0.5f);
+
+ clearInvocations(mBrightnessMappingStrategy);
+
+ // Verify short term model is not learnt when RBC is disabled
+ mController.recalculateSplines(false, adjustments);
+ verify(mBrightnessMappingStrategy).clearUserDataPoints();
+ verify(mBrightnessMappingStrategy).recalculateSplines(false, adjustments);
+ verifyNoMoreInteractions(mBrightnessMappingStrategy);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index 1e97c1c..5f1ff6b 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -287,7 +287,7 @@
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
- final int displayIds[] = bs.getDisplayIds();
+ final int[] displayIds = bs.getDisplayIds(/* includeDisabled= */ false);
final int size = displayIds.length;
assertTrue(size > 0);
@@ -297,7 +297,9 @@
);
for (int i = 0; i < size; i++) {
DisplayInfo info = bs.getDisplayInfo(displayIds[i]);
- assertTrue(expectedDisplayTypeToViewPortTypeMapping.keySet().contains(info.type));
+ if (info != null) {
+ assertTrue(expectedDisplayTypeToViewPortTypeMapping.keySet().contains(info.type));
+ }
}
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
@@ -1174,7 +1176,8 @@
DisplayManagerService.BinderService displayManagerBinderService,
FakeDisplayDevice displayDevice) {
- final int[] displayIds = displayManagerBinderService.getDisplayIds();
+ final int[] displayIds = displayManagerBinderService.getDisplayIds(
+ /* includeDisabled= */ false);
assertTrue(displayIds.length > 0);
int displayId = Display.INVALID_DISPLAY;
for (int i = 0; i < displayIds.length; i++) {
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
index cc68ba8..5b13145 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -33,6 +33,7 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -53,6 +54,8 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.display.layout.Layout;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -79,6 +82,7 @@
private TestLooper mLooper;
private Handler mHandler;
private PowerManager mPowerManager;
+ private DeviceStateToLayoutMap mDeviceStateToLayoutMapSpy;
@Mock LogicalDisplayMapper.Listener mListenerMock;
@Mock Context mContextMock;
@@ -133,8 +137,11 @@
mLooper = new TestLooper();
mHandler = new Handler(mLooper.getLooper());
+
+ mDeviceStateToLayoutMapSpy = spy(new DeviceStateToLayoutMap());
mLogicalDisplayMapper = new LogicalDisplayMapper(mContextMock, mDisplayDeviceRepo,
- mListenerMock, new DisplayManagerService.SyncRoot(), mHandler);
+ mListenerMock, new DisplayManagerService.SyncRoot(), mHandler,
+ mDeviceStateToLayoutMapSpy);
}
@@ -413,6 +420,86 @@
/* isBootCompleted= */true));
}
+ @Test public void testEnabledAndDisabledDisplays() {
+ DisplayAddress displayAddressOne = new TestUtils.TestDisplayAddress();
+ DisplayAddress displayAddressTwo = new TestUtils.TestDisplayAddress();
+ DisplayAddress displayAddressThree = new TestUtils.TestDisplayAddress();
+
+ TestDisplayDevice device1 = createDisplayDevice(displayAddressOne, Display.TYPE_INTERNAL,
+ 600, 800,
+ DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
+ TestDisplayDevice device2 = createDisplayDevice(displayAddressTwo, Display.TYPE_INTERNAL,
+ 200, 800,
+ DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
+ TestDisplayDevice device3 = createDisplayDevice(displayAddressThree, Display.TYPE_INTERNAL,
+ 600, 900, DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
+
+ Layout threeDevicesEnabledLayout = new Layout();
+ threeDevicesEnabledLayout.createDisplayLocked(
+ displayAddressOne,
+ /* isDefault= */ true,
+ /* isEnabled= */ true);
+
+ threeDevicesEnabledLayout.createDisplayLocked(
+ displayAddressTwo,
+ /* isDefault= */ false,
+ /* isEnabled= */ true);
+ threeDevicesEnabledLayout.createDisplayLocked(
+ displayAddressThree,
+ /* isDefault= */ false,
+ /* isEnabled= */ true);
+
+ when(mDeviceStateToLayoutMapSpy.get(DeviceStateToLayoutMap.STATE_DEFAULT))
+ .thenReturn(threeDevicesEnabledLayout);
+
+ LogicalDisplay display1 = add(device1);
+ LogicalDisplay display2 = add(device2);
+ LogicalDisplay display3 = add(device3);
+
+ // ensure 3 displays are returned
+ int [] ids = mLogicalDisplayMapper.getDisplayIdsLocked(Process.SYSTEM_UID);
+ assertEquals(3, ids.length);
+ Arrays.sort(ids);
+ assertEquals(DEFAULT_DISPLAY, ids[0]);
+
+ Layout oneDeviceEnabledLayout = new Layout();
+ oneDeviceEnabledLayout.createDisplayLocked(
+ display1.getDisplayInfoLocked().address,
+ /* isDefault= */ true,
+ /* isEnabled= */ true);
+ oneDeviceEnabledLayout.createDisplayLocked(
+ display2.getDisplayInfoLocked().address,
+ /* isDefault= */ false,
+ /* isEnabled= */ false);
+ oneDeviceEnabledLayout.createDisplayLocked(
+ display3.getDisplayInfoLocked().address,
+ /* isDefault= */ false,
+ /* isEnabled= */ false);
+
+ when(mDeviceStateToLayoutMapSpy.get(0)).thenReturn(oneDeviceEnabledLayout);
+ when(mDeviceStateToLayoutMapSpy.get(1)).thenReturn(threeDevicesEnabledLayout);
+
+ mLogicalDisplayMapper
+ .setDeviceStateLocked(0, false);
+ mDisplayDeviceRepo.onDisplayDeviceEvent(device3, DISPLAY_DEVICE_EVENT_CHANGED);
+ final int[] allDisplayIds = mLogicalDisplayMapper.getDisplayIdsLocked(
+ Process.SYSTEM_UID, false);
+ mLooper.dispatchAll();
+
+ // ensure only one display is returned
+ assertEquals(1, allDisplayIds.length);
+
+ mLogicalDisplayMapper
+ .setDeviceStateLocked(1, false);
+ mDisplayDeviceRepo.onDisplayDeviceEvent(device3, DISPLAY_DEVICE_EVENT_CHANGED);
+ final int[] threeDisplaysEnabled = mLogicalDisplayMapper.getDisplayIdsLocked(
+ Process.SYSTEM_UID, false);
+ mLooper.dispatchAll();
+
+ // ensure all three displays are returned
+ assertEquals(3, threeDisplaysEnabled.length);
+ }
+
/////////////////
// Helper Methods
/////////////////
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index 758a56f..e9171c0c 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -393,14 +393,14 @@
+ " <library \n"
+ " name=\"foo\"\n"
+ " file=\"" + mFooJar + "\"\n"
- + " on-bootclasspath-before=\"A\"\n"
+ + " on-bootclasspath-before=\"Q\"\n"
+ " on-bootclasspath-since=\"W\"\n"
+ " />\n\n"
+ " </permissions>";
parseSharedLibraries(contents);
assertFooIsOnlySharedLibrary();
SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
- assertThat(entry.onBootclasspathBefore).isEqualTo("A");
+ assertThat(entry.onBootclasspathBefore).isEqualTo("Q");
assertThat(entry.onBootclasspathSince).isEqualTo("W");
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 8c4a4c9..03d8774 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -2811,12 +2811,18 @@
true, false, false, false);
waitUntilHandlersIdle();
+ final WindowState startingWindow = activityTop.mStartingWindow;
+ assertNotNull(startingWindow);
+
// Make the top one invisible, and try transferring the starting window from the top to the
// bottom one.
activityTop.setVisibility(false, false);
activityBottom.transferStartingWindowFromHiddenAboveTokenIfNeeded();
waitUntilHandlersIdle();
+ // Expect getFrozenInsetsState will be null when transferring the starting window.
+ assertNull(startingWindow.getFrozenInsetsState());
+
// Assert that the bottom window now has the starting window.
assertNoStartingWindow(activityTop);
assertHasStartingWindow(activityBottom);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncerTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncerTest.java
index cc28ea6..8738295 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncerTest.java
@@ -48,11 +48,11 @@
public void testSyncOne() throws InterruptedException {
final CountDownLatch finishedLatch = new CountDownLatch(1);
int startSyncId = mSurfaceSyncer.setupSync(transaction -> finishedLatch.countDown());
- Syncable syncable = new Syncable();
- mSurfaceSyncer.addToSync(startSyncId, syncable);
+ SyncTarget syncTarget = new SyncTarget();
+ mSurfaceSyncer.addToSync(startSyncId, syncTarget);
mSurfaceSyncer.markSyncReady(startSyncId);
- syncable.onBufferReady();
+ syncTarget.onBufferReady();
finishedLatch.await(5, TimeUnit.SECONDS);
assertEquals(0, finishedLatch.getCount());
@@ -62,22 +62,22 @@
public void testSyncMultiple() throws InterruptedException {
final CountDownLatch finishedLatch = new CountDownLatch(1);
int startSyncId = mSurfaceSyncer.setupSync(transaction -> finishedLatch.countDown());
- Syncable syncable1 = new Syncable();
- Syncable syncable2 = new Syncable();
- Syncable syncable3 = new Syncable();
+ SyncTarget syncTarget1 = new SyncTarget();
+ SyncTarget syncTarget2 = new SyncTarget();
+ SyncTarget syncTarget3 = new SyncTarget();
- mSurfaceSyncer.addToSync(startSyncId, syncable1);
- mSurfaceSyncer.addToSync(startSyncId, syncable2);
- mSurfaceSyncer.addToSync(startSyncId, syncable3);
+ mSurfaceSyncer.addToSync(startSyncId, syncTarget1);
+ mSurfaceSyncer.addToSync(startSyncId, syncTarget2);
+ mSurfaceSyncer.addToSync(startSyncId, syncTarget3);
mSurfaceSyncer.markSyncReady(startSyncId);
- syncable1.onBufferReady();
+ syncTarget1.onBufferReady();
assertNotEquals(0, finishedLatch.getCount());
- syncable3.onBufferReady();
+ syncTarget3.onBufferReady();
assertNotEquals(0, finishedLatch.getCount());
- syncable2.onBufferReady();
+ syncTarget2.onBufferReady();
finishedLatch.await(5, TimeUnit.SECONDS);
assertEquals(0, finishedLatch.getCount());
@@ -85,7 +85,7 @@
@Test
public void testInvalidSyncId() {
- assertFalse(mSurfaceSyncer.addToSync(0, new Syncable()));
+ assertFalse(mSurfaceSyncer.addToSync(0, new SyncTarget()));
}
@Test
@@ -93,14 +93,14 @@
final CountDownLatch finishedLatch = new CountDownLatch(1);
int startSyncId = mSurfaceSyncer.setupSync(transaction -> finishedLatch.countDown());
- Syncable syncable1 = new Syncable();
- Syncable syncable2 = new Syncable();
+ SyncTarget syncTarget1 = new SyncTarget();
+ SyncTarget syncTarget2 = new SyncTarget();
- assertTrue(mSurfaceSyncer.addToSync(startSyncId, syncable1));
+ assertTrue(mSurfaceSyncer.addToSync(startSyncId, syncTarget1));
mSurfaceSyncer.markSyncReady(startSyncId);
// Adding to a sync that has been completed is also invalid since the sync id has been
// cleared.
- assertFalse(mSurfaceSyncer.addToSync(startSyncId, syncable2));
+ assertFalse(mSurfaceSyncer.addToSync(startSyncId, syncTarget2));
}
@Test
@@ -110,27 +110,89 @@
int startSyncId1 = mSurfaceSyncer.setupSync(transaction -> finishedLatch1.countDown());
int startSyncId2 = mSurfaceSyncer.setupSync(transaction -> finishedLatch2.countDown());
- Syncable syncable1 = new Syncable();
- Syncable syncable2 = new Syncable();
+ SyncTarget syncTarget1 = new SyncTarget();
+ SyncTarget syncTarget2 = new SyncTarget();
- assertTrue(mSurfaceSyncer.addToSync(startSyncId1, syncable1));
- assertTrue(mSurfaceSyncer.addToSync(startSyncId2, syncable2));
+ assertTrue(mSurfaceSyncer.addToSync(startSyncId1, syncTarget1));
+ assertTrue(mSurfaceSyncer.addToSync(startSyncId2, syncTarget2));
mSurfaceSyncer.markSyncReady(startSyncId1);
mSurfaceSyncer.markSyncReady(startSyncId2);
- syncable1.onBufferReady();
+ syncTarget1.onBufferReady();
finishedLatch1.await(5, TimeUnit.SECONDS);
assertEquals(0, finishedLatch1.getCount());
assertNotEquals(0, finishedLatch2.getCount());
- syncable2.onBufferReady();
+ syncTarget2.onBufferReady();
finishedLatch2.await(5, TimeUnit.SECONDS);
assertEquals(0, finishedLatch2.getCount());
}
- private static class Syncable implements SurfaceSyncer.SyncTarget {
+ @Test
+ public void testMergeSync() throws InterruptedException {
+ final CountDownLatch finishedLatch1 = new CountDownLatch(1);
+ final CountDownLatch finishedLatch2 = new CountDownLatch(1);
+ int startSyncId1 = mSurfaceSyncer.setupSync(transaction -> finishedLatch1.countDown());
+ int startSyncId2 = mSurfaceSyncer.setupSync(transaction -> finishedLatch2.countDown());
+
+ SyncTarget syncTarget1 = new SyncTarget();
+ SyncTarget syncTarget2 = new SyncTarget();
+
+ assertTrue(mSurfaceSyncer.addToSync(startSyncId1, syncTarget1));
+ assertTrue(mSurfaceSyncer.addToSync(startSyncId2, syncTarget2));
+ mSurfaceSyncer.markSyncReady(startSyncId1);
+ mSurfaceSyncer.merge(startSyncId2, startSyncId1, mSurfaceSyncer);
+ mSurfaceSyncer.markSyncReady(startSyncId2);
+
+ // Finish syncTarget2 first to test that the syncSet is not complete until the merged sync
+ // is also done.
+ syncTarget2.onBufferReady();
+ finishedLatch2.await(1, TimeUnit.SECONDS);
+ // Sync did not complete yet
+ assertNotEquals(0, finishedLatch2.getCount());
+
+ syncTarget1.onBufferReady();
+
+ // The first sync will still get a callback when it's sync requirements are done.
+ finishedLatch1.await(5, TimeUnit.SECONDS);
+ assertEquals(0, finishedLatch1.getCount());
+
+ finishedLatch2.await(5, TimeUnit.SECONDS);
+ assertEquals(0, finishedLatch2.getCount());
+ }
+
+ @Test
+ public void testMergeSyncAlreadyComplete() throws InterruptedException {
+ final CountDownLatch finishedLatch1 = new CountDownLatch(1);
+ final CountDownLatch finishedLatch2 = new CountDownLatch(1);
+ int startSyncId1 = mSurfaceSyncer.setupSync(transaction -> finishedLatch1.countDown());
+ int startSyncId2 = mSurfaceSyncer.setupSync(transaction -> finishedLatch2.countDown());
+
+ SyncTarget syncTarget1 = new SyncTarget();
+ SyncTarget syncTarget2 = new SyncTarget();
+
+ assertTrue(mSurfaceSyncer.addToSync(startSyncId1, syncTarget1));
+ assertTrue(mSurfaceSyncer.addToSync(startSyncId2, syncTarget2));
+ mSurfaceSyncer.markSyncReady(startSyncId1);
+ syncTarget1.onBufferReady();
+
+ // The first sync will still get a callback when it's sync requirements are done.
+ finishedLatch1.await(5, TimeUnit.SECONDS);
+ assertEquals(0, finishedLatch1.getCount());
+
+ mSurfaceSyncer.merge(startSyncId2, startSyncId1, mSurfaceSyncer);
+ mSurfaceSyncer.markSyncReady(startSyncId2);
+ syncTarget2.onBufferReady();
+
+ // Verify that the second sync will receive complete since the merged sync was already
+ // completed before the merge.
+ finishedLatch2.await(5, TimeUnit.SECONDS);
+ assertEquals(0, finishedLatch2.getCount());
+ }
+
+ private static class SyncTarget implements SurfaceSyncer.SyncTarget {
private SurfaceSyncer.SyncBufferCallback mSyncBufferCallback;
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index 5340a79..8202cd9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -24,6 +24,8 @@
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.android.server.wm.testing.Assert.assertThrows;
+import static com.google.common.truth.Truth.assertWithMessage;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -43,6 +45,7 @@
import static org.mockito.Mockito.verify;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Binder;
@@ -78,6 +81,7 @@
private static final int TASK_ID = 10;
private TaskFragmentOrganizerController mController;
+ private WindowOrganizerController mWindowOrganizerController;
private TaskFragmentOrganizer mOrganizer;
private TaskFragmentOrganizerToken mOrganizerToken;
private ITaskFragmentOrganizer mIOrganizer;
@@ -87,10 +91,13 @@
private WindowContainerTransaction mTransaction;
private WindowContainerToken mFragmentWindowToken;
private RemoteAnimationDefinition mDefinition;
+ private IBinder mErrorToken;
+ private Rect mTaskFragBounds;
@Before
public void setup() {
- mController = mAtm.mWindowOrganizerController.mTaskFragmentOrganizerController;
+ mWindowOrganizerController = mAtm.mWindowOrganizerController;
+ mController = mWindowOrganizerController.mTaskFragmentOrganizerController;
mOrganizer = new TaskFragmentOrganizer(Runnable::run);
mOrganizerToken = mOrganizer.getOrganizerToken();
mIOrganizer = ITaskFragmentOrganizer.Stub.asInterface(mOrganizerToken.asBinder());
@@ -101,6 +108,10 @@
mTransaction = new WindowContainerTransaction();
mFragmentWindowToken = mTaskFragment.mRemoteToken.toWindowContainerToken();
mDefinition = new RemoteAnimationDefinition();
+ mErrorToken = new Binder();
+ final Rect displayBounds = mDisplayContent.getBounds();
+ mTaskFragBounds = new Rect(displayBounds.left, displayBounds.top, displayBounds.centerX(),
+ displayBounds.centerY());
spyOn(mController);
spyOn(mOrganizer);
@@ -221,16 +232,15 @@
}
@Test
- public void testOnTaskFragmentError() throws RemoteException {
- final IBinder errorCallbackToken = new Binder();
+ public void testOnTaskFragmentError() {
final Throwable exception = new IllegalArgumentException("Test exception");
mController.registerOrganizer(mIOrganizer);
mController.onTaskFragmentError(mTaskFragment.getTaskFragmentOrganizer(),
- errorCallbackToken, exception);
+ mErrorToken, exception);
mController.dispatchPendingEvents();
- verify(mOrganizer).onTaskFragmentError(eq(errorCallbackToken), eq(exception));
+ verify(mOrganizer).onTaskFragmentError(eq(mErrorToken), eq(exception));
}
@Test
@@ -280,7 +290,7 @@
final int uid = Binder.getCallingUid();
mTaskFragment.setTaskFragmentOrganizer(mOrganizer.getOrganizerToken(), uid,
DEFAULT_TASK_FRAGMENT_ORGANIZER_PROCESS_NAME);
- mAtm.mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
mController.registerOrganizer(mIOrganizer);
mOrganizer.applyTransaction(mTransaction);
final Task task = createTask(mDisplayContent);
@@ -305,7 +315,7 @@
final IBinder temporaryToken = token.getValue();
assertNotEquals(activity.token, temporaryToken);
mTransaction.reparentActivityToTaskFragment(mFragmentToken, temporaryToken);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ mWindowOrganizerController.applyTransaction(mTransaction);
assertEquals(mTaskFragment, activity.getTaskFragment());
// The temporary token can only be used once.
@@ -395,8 +405,7 @@
// No lifecycle update when the TaskFragment is not recorded.
verify(mAtm.mRootWindowContainer, never()).resumeFocusedTasksTopActivities();
- mAtm.mWindowOrganizerController.mLaunchTaskFragments
- .put(mFragmentToken, mTaskFragment);
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
assertApplyTransactionAllowed(mTransaction);
verify(mAtm.mRootWindowContainer).resumeFocusedTasksTopActivities();
@@ -466,23 +475,23 @@
// Fail to create TaskFragment when the task uid is different from caller.
activity.info.applicationInfo.uid = uid;
activity.getTask().effectiveUid = uid + 1;
- mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
+ mWindowOrganizerController.applyTransaction(mTransaction);
- assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
+ assertNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
// Fail to create TaskFragment when the task uid is different from owner activity.
activity.info.applicationInfo.uid = uid + 1;
activity.getTask().effectiveUid = uid;
- mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
+ mWindowOrganizerController.applyTransaction(mTransaction);
- assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
+ assertNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
// Successfully created a TaskFragment for same uid.
activity.info.applicationInfo.uid = uid;
activity.getTask().effectiveUid = uid;
- mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
+ mWindowOrganizerController.applyTransaction(mTransaction);
- assertNotNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
+ assertNotNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
}
@Test
@@ -519,7 +528,7 @@
.setParentTask(task)
.setFragmentToken(mFragmentToken)
.build();
- mAtm.mWindowOrganizerController.mLaunchTaskFragments
+ mWindowOrganizerController.mLaunchTaskFragments
.put(mFragmentToken, mTaskFragment);
mTransaction.reparentActivityToTaskFragment(mFragmentToken, activity.token);
doReturn(true).when(mTaskFragment).isAllowedToEmbedActivity(activity);
@@ -549,8 +558,8 @@
.setOrganizer(mOrganizer)
.createActivityCount(1)
.build();
- mAtm.mWindowOrganizerController.mLaunchTaskFragments.put(token0, tf0);
- mAtm.mWindowOrganizerController.mLaunchTaskFragments.put(token1, tf1);
+ mWindowOrganizerController.mLaunchTaskFragments.put(token0, tf0);
+ mWindowOrganizerController.mLaunchTaskFragments.put(token1, tf1);
final ActivityRecord activity0 = tf0.getTopMostActivity();
final ActivityRecord activity1 = tf1.getTopMostActivity();
@@ -558,7 +567,7 @@
final ActivityRecord activityInOtherTask = createActivityRecord(mDefaultDisplay);
mDisplayContent.setFocusedApp(activityInOtherTask);
mTransaction.requestFocusOnTaskFragment(token0);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ mWindowOrganizerController.applyTransaction(mTransaction);
assertEquals(activityInOtherTask, mDisplayContent.mFocusedApp);
@@ -566,7 +575,7 @@
activity0.setState(ActivityRecord.State.PAUSED, "test");
activity1.setState(ActivityRecord.State.RESUMED, "test");
mDisplayContent.setFocusedApp(activity1);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ mWindowOrganizerController.applyTransaction(mTransaction);
assertEquals(activity1, mDisplayContent.mFocusedApp);
@@ -574,7 +583,7 @@
// has a resumed activity.
activity0.setState(ActivityRecord.State.RESUMED, "test");
mDisplayContent.setFocusedApp(activity1);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ mWindowOrganizerController.applyTransaction(mTransaction);
assertEquals(activity0, mDisplayContent.mFocusedApp);
}
@@ -583,53 +592,50 @@
public void testTaskFragmentInPip_startActivityInTaskFragment() {
setupTaskFragmentInPip();
final ActivityRecord activity = mTaskFragment.getTopMostActivity();
- final IBinder errorToken = new Binder();
spyOn(mAtm.getActivityStartController());
- spyOn(mAtm.mWindowOrganizerController);
+ spyOn(mWindowOrganizerController);
// Not allow to start activity in a TaskFragment that is in a PIP Task.
mTransaction.startActivityInTaskFragment(
mFragmentToken, activity.token, new Intent(), null /* activityOptions */)
- .setErrorCallbackToken(errorToken);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ .setErrorCallbackToken(mErrorToken);
+ mWindowOrganizerController.applyTransaction(mTransaction);
verify(mAtm.getActivityStartController(), never()).startActivityInTaskFragment(any(), any(),
- any(), any(), anyInt(), anyInt());
+ any(), any(), anyInt(), anyInt(), any());
verify(mAtm.mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
- eq(errorToken), any(IllegalArgumentException.class));
+ eq(mErrorToken), any(IllegalArgumentException.class));
}
@Test
public void testTaskFragmentInPip_reparentActivityToTaskFragment() {
setupTaskFragmentInPip();
final ActivityRecord activity = createActivityRecord(mDisplayContent);
- final IBinder errorToken = new Binder();
- spyOn(mAtm.mWindowOrganizerController);
+ spyOn(mWindowOrganizerController);
// Not allow to reparent activity to a TaskFragment that is in a PIP Task.
mTransaction.reparentActivityToTaskFragment(mFragmentToken, activity.token)
- .setErrorCallbackToken(errorToken);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ .setErrorCallbackToken(mErrorToken);
+ mWindowOrganizerController.applyTransaction(mTransaction);
- verify(mAtm.mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
- eq(errorToken), any(IllegalArgumentException.class));
+ verify(mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
+ eq(mErrorToken), any(IllegalArgumentException.class));
assertNull(activity.getOrganizedTaskFragment());
}
@Test
public void testTaskFragmentInPip_setAdjacentTaskFragment() {
setupTaskFragmentInPip();
- final IBinder errorToken = new Binder();
- spyOn(mAtm.mWindowOrganizerController);
+ spyOn(mWindowOrganizerController);
// Not allow to set adjacent on a TaskFragment that is in a PIP Task.
mTransaction.setAdjacentTaskFragments(mFragmentToken, null /* fragmentToken2 */,
null /* options */)
- .setErrorCallbackToken(errorToken);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ .setErrorCallbackToken(mErrorToken);
+ mWindowOrganizerController.applyTransaction(mTransaction);
- verify(mAtm.mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
- eq(errorToken), any(IllegalArgumentException.class));
+ verify(mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
+ eq(mErrorToken), any(IllegalArgumentException.class));
verify(mTaskFragment, never()).setAdjacentTaskFragment(any(), anyBoolean());
}
@@ -640,47 +646,45 @@
ACTIVITY_TYPE_STANDARD);
final ActivityRecord activity = createActivityRecord(pipTask);
final IBinder fragmentToken = new Binder();
- final IBinder errorToken = new Binder();
- spyOn(mAtm.mWindowOrganizerController);
+ spyOn(mWindowOrganizerController);
// Not allow to create TaskFragment in a PIP Task.
createTaskFragmentFromOrganizer(mTransaction, activity, fragmentToken);
- mTransaction.setErrorCallbackToken(errorToken);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ mTransaction.setErrorCallbackToken(mErrorToken);
+ mWindowOrganizerController.applyTransaction(mTransaction);
- verify(mAtm.mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
- eq(errorToken), any(IllegalArgumentException.class));
- assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
+ verify(mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
+ eq(mErrorToken), any(IllegalArgumentException.class));
+ assertNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
}
@Test
public void testTaskFragmentInPip_deleteTaskFragment() {
setupTaskFragmentInPip();
- final IBinder errorToken = new Binder();
- spyOn(mAtm.mWindowOrganizerController);
+ spyOn(mWindowOrganizerController);
// Not allow to delete a TaskFragment that is in a PIP Task.
mTransaction.deleteTaskFragment(mFragmentWindowToken)
- .setErrorCallbackToken(errorToken);
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ .setErrorCallbackToken(mErrorToken);
+ mWindowOrganizerController.applyTransaction(mTransaction);
- verify(mAtm.mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
- eq(errorToken), any(IllegalArgumentException.class));
- assertNotNull(mAtm.mWindowOrganizerController.getTaskFragment(mFragmentToken));
+ verify(mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer),
+ eq(mErrorToken), any(IllegalArgumentException.class));
+ assertNotNull(mWindowOrganizerController.getTaskFragment(mFragmentToken));
// Allow organizer to delete empty TaskFragment for cleanup.
final Task task = mTaskFragment.getTask();
mTaskFragment.removeChild(mTaskFragment.getTopMostActivity());
- mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
+ mWindowOrganizerController.applyTransaction(mTransaction);
- assertNull(mAtm.mWindowOrganizerController.getTaskFragment(mFragmentToken));
+ assertNull(mWindowOrganizerController.getTaskFragment(mFragmentToken));
assertNull(task.getTopChild());
}
@Test
public void testTaskFragmentInPip_setConfig() {
setupTaskFragmentInPip();
- spyOn(mAtm.mWindowOrganizerController);
+ spyOn(mWindowOrganizerController);
// Set bounds is ignored on a TaskFragment that is in a PIP Task.
mTransaction.setBounds(mFragmentWindowToken, new Rect(0, 0, 100, 100));
@@ -832,14 +836,13 @@
final IBinder fragmentToken = new Binder();
createTaskFragmentFromOrganizer(mTransaction, ownerActivity, fragmentToken);
mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
- final TaskFragment taskFragment = mAtm.mWindowOrganizerController
- .getTaskFragment(fragmentToken);
+ final TaskFragment taskFragment = mWindowOrganizerController.getTaskFragment(fragmentToken);
assertNotNull(taskFragment);
taskFragment.removeImmediately();
- assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
+ assertNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
}
/**
@@ -902,6 +905,101 @@
assertApplyTransactionDisallowed(mTransaction);
}
+ // TODO(b/232871351): add test for minimum dimension violation in startActivityInTaskFragment
+ @Test
+ public void testMinDimensionViolation_ReparentActivityToTaskFragment() {
+ final Task task = createTask(mDisplayContent);
+ final ActivityRecord activity = createActivityRecord(task);
+ // Make minWidth/minHeight exceeds the TaskFragment bounds.
+ activity.info.windowLayout = new ActivityInfo.WindowLayout(
+ 0, 0, 0, 0, 0, mTaskFragBounds.width() + 10, mTaskFragBounds.height() + 10);
+ mOrganizer.applyTransaction(mTransaction);
+ mController.registerOrganizer(mIOrganizer);
+ mTaskFragment = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .setFragmentToken(mFragmentToken)
+ .setOrganizer(mOrganizer)
+ .setBounds(mTaskFragBounds)
+ .build();
+ doReturn(true).when(mTaskFragment).isAllowedToEmbedActivity(activity);
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
+ clearInvocations(mAtm.mRootWindowContainer);
+
+ // Reparent activity to mTaskFragment, which is smaller than activity's
+ // minimum dimensions.
+ mTransaction.reparentActivityToTaskFragment(mFragmentToken, activity.token)
+ .setErrorCallbackToken(mErrorToken);
+ mWindowOrganizerController.applyTransaction(mTransaction);
+
+ verify(mOrganizer).onTaskFragmentError(eq(mErrorToken), any(SecurityException.class));
+ }
+
+ @Test
+ public void testMinDimensionViolation_ReparentChildren() {
+ final Task task = createTask(mDisplayContent);
+ mOrganizer.applyTransaction(mTransaction);
+ mController.registerOrganizer(mIOrganizer);
+ final IBinder oldFragToken = new Binder();
+ final TaskFragment oldTaskFrag = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .createActivityCount(1)
+ .setFragmentToken(oldFragToken)
+ .setOrganizer(mOrganizer)
+ .build();
+ final ActivityRecord activity = oldTaskFrag.getTopMostActivity();
+ // Make minWidth/minHeight exceeds mTaskFragment bounds.
+ activity.info.windowLayout = new ActivityInfo.WindowLayout(
+ 0, 0, 0, 0, 0, mTaskFragBounds.width() + 10, mTaskFragBounds.height() + 10);
+ mTaskFragment = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .setFragmentToken(mFragmentToken)
+ .setOrganizer(mOrganizer)
+ .setBounds(mTaskFragBounds)
+ .build();
+ doReturn(true).when(mTaskFragment).isAllowedToEmbedActivity(activity);
+ mWindowOrganizerController.mLaunchTaskFragments.put(oldFragToken, oldTaskFrag);
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
+ clearInvocations(mAtm.mRootWindowContainer);
+
+ // Reparent oldTaskFrag's children to mTaskFragment, which is smaller than activity's
+ // minimum dimensions.
+ mTransaction.reparentChildren(oldTaskFrag.mRemoteToken.toWindowContainerToken(),
+ mTaskFragment.mRemoteToken.toWindowContainerToken())
+ .setErrorCallbackToken(mErrorToken);
+ mWindowOrganizerController.applyTransaction(mTransaction);
+
+ verify(mOrganizer).onTaskFragmentError(eq(mErrorToken), any(SecurityException.class));
+ }
+
+ @Test
+ public void testMinDimensionViolation_SetBounds() {
+ final Task task = createTask(mDisplayContent);
+ mOrganizer.applyTransaction(mTransaction);
+ mController.registerOrganizer(mIOrganizer);
+ mTaskFragment = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .createActivityCount(1)
+ .setFragmentToken(mFragmentToken)
+ .setOrganizer(mOrganizer)
+ .setBounds(new Rect(0, 0, mTaskFragBounds.right * 2, mTaskFragBounds.bottom * 2))
+ .build();
+ final ActivityRecord activity = mTaskFragment.getTopMostActivity();
+ // Make minWidth/minHeight exceeds the TaskFragment bounds.
+ activity.info.windowLayout = new ActivityInfo.WindowLayout(
+ 0, 0, 0, 0, 0, mTaskFragBounds.width() + 10, mTaskFragBounds.height() + 10);
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
+ clearInvocations(mAtm.mRootWindowContainer);
+
+ // Shrink the TaskFragment to mTaskFragBounds to make its bounds smaller than activity's
+ // minimum dimensions.
+ mTransaction.setBounds(mTaskFragment.mRemoteToken.toWindowContainerToken(), mTaskFragBounds)
+ .setErrorCallbackToken(mErrorToken);
+ mWindowOrganizerController.applyTransaction(mTransaction);
+
+ assertWithMessage("setBounds must not be performed.")
+ .that(mTaskFragment.getBounds()).isEqualTo(task.getBounds());
+ }
+
/**
* Creates a {@link TaskFragment} with the {@link WindowContainerTransaction}. Calls
* {@link WindowOrganizerController#applyTransaction} to apply the transaction,
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 9957d05..20fbda4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -1199,6 +1199,7 @@
@Nullable
private TaskFragmentOrganizer mOrganizer;
private IBinder mFragmentToken;
+ private Rect mBounds;
TaskFragmentBuilder(ActivityTaskManagerService service) {
mAtm = service;
@@ -1235,6 +1236,11 @@
return this;
}
+ TaskFragmentBuilder setBounds(@Nullable Rect bounds) {
+ mBounds = bounds;
+ return this;
+ }
+
TaskFragment build() {
SystemServicesTestRule.checkHoldsLock(mAtm.mGlobalLock);
@@ -1262,6 +1268,9 @@
mOrganizer.getOrganizerToken(), DEFAULT_TASK_FRAGMENT_ORGANIZER_UID,
DEFAULT_TASK_FRAGMENT_ORGANIZER_PROCESS_NAME);
}
+ if (mBounds != null && !mBounds.isEmpty()) {
+ taskFragment.setBounds(mBounds);
+ }
spyOn(taskFragment);
return taskFragment;
}