Merge "Fixed an issue where the heads up were not rounded during bypass" into sc-dev
diff --git a/apct-tests/perftests/multiuser/Android.bp b/apct-tests/perftests/multiuser/Android.bp
index 917753e..c967e51 100644
--- a/apct-tests/perftests/multiuser/Android.bp
+++ b/apct-tests/perftests/multiuser/Android.bp
@@ -31,6 +31,6 @@
],
platform_apis: true,
test_suites: ["device-tests"],
- data: [":perfetto_artifacts"],
+ data: ["trace_configs/*"],
certificate: "platform",
}
diff --git a/apct-tests/perftests/multiuser/AndroidManifest.xml b/apct-tests/perftests/multiuser/AndroidManifest.xml
index 9553304..63e5983 100644
--- a/apct-tests/perftests/multiuser/AndroidManifest.xml
+++ b/apct-tests/perftests/multiuser/AndroidManifest.xml
@@ -20,10 +20,12 @@
<uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
<uses-permission android:name="android.permission.DEVICE_POWER" />
- <uses-permission android:name="android.permission.MANAGE_USERS" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+ <uses-permission android:name="android.permission.MANAGE_USERS" />
+ <uses-permission android:name="android.permission.REAL_GET_TASKS" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<application>
diff --git a/apct-tests/perftests/multiuser/AndroidTest.xml b/apct-tests/perftests/multiuser/AndroidTest.xml
index fbe5892..8e342f3 100644
--- a/apct-tests/perftests/multiuser/AndroidTest.xml
+++ b/apct-tests/perftests/multiuser/AndroidTest.xml
@@ -26,7 +26,7 @@
<!-- Needed for pushing the trace config file -->
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
- <option name="push-file" key="trace_config_detailed.textproto" value="/data/misc/perfetto-traces/trace_config.textproto" />
+ <option name="push-file" key="trace_config_multi_user.textproto" value="/data/misc/perfetto-traces/trace_config.textproto" />
<!--Install the content provider automatically when we push some file in sdcard folder.-->
<!--Needed to avoid the installation during the test suite.-->
<option name="push-file" key="trace_config_detailed.textproto" value="/sdcard/sample.textproto" />
diff --git a/apct-tests/perftests/multiuser/trace_configs/trace_config_multi_user.textproto b/apct-tests/perftests/multiuser/trace_configs/trace_config_multi_user.textproto
new file mode 100644
index 0000000..14a3f8f
--- /dev/null
+++ b/apct-tests/perftests/multiuser/trace_configs/trace_config_multi_user.textproto
@@ -0,0 +1,154 @@
+# Copyright (C) 2021 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.
+
+# proto-message: TraceConfig
+
+# Enable periodic flushing of the trace buffer into the output file.
+write_into_file: true
+
+# Writes the userspace buffer into the file every 1s.
+file_write_period_ms: 1000
+
+# See b/126487238 - we need to guarantee ordering of events.
+flush_period_ms: 10000
+
+# The trace buffers needs to be big enough to hold |file_write_period_ms| of
+# trace data. The trace buffer sizing depends on the number of trace categories
+# enabled and the device activity.
+
+# RSS events
+buffers {
+ size_kb: 32768
+ fill_policy: RING_BUFFER
+}
+
+# procfs polling
+buffers {
+ size_kb: 8192
+ fill_policy: RING_BUFFER
+}
+
+data_sources {
+ config {
+ name: "linux.ftrace"
+ target_buffer: 0
+ ftrace_config {
+ # These parameters affect only the kernel trace buffer size and how
+ # frequently it gets moved into the userspace buffer defined above.
+ buffer_size_kb: 16384
+ drain_period_ms: 250
+
+ # Store certain high-volume "sched" ftrace events in a denser format
+ # (falling back to the default format if not supported by the tracer).
+ compact_sched {
+ enabled: true
+ }
+
+ # Enables symbol name resolution against /proc/kallsyms
+ symbolize_ksyms: true
+
+ # We need to do process tracking to ensure kernel ftrace events targeted at short-lived
+ # threads are associated correctly
+ ftrace_events: "task/task_newtask"
+ ftrace_events: "task/task_rename"
+ ftrace_events: "sched/sched_process_exit"
+ ftrace_events: "sched/sched_process_free"
+
+ # Memory events
+ ftrace_events: "rss_stat"
+ ftrace_events: "ion_heap_shrink"
+ ftrace_events: "ion_heap_grow"
+ ftrace_events: "ion/ion_stat"
+ ftrace_events: "dmabuf_heap/dma_heap_stat"
+ ftrace_events: "oom_score_adj_update"
+ ftrace_events: "gpu_mem/gpu_mem_total"
+
+ # Old (kernel) LMK
+ ftrace_events: "lowmemorykiller/lowmemory_kill"
+
+ atrace_apps: "*"
+
+ atrace_categories: "am"
+ atrace_categories: "bionic"
+ atrace_categories: "camera"
+ atrace_categories: "wm"
+ atrace_categories: "dalvik"
+ atrace_categories: "sched"
+ atrace_categories: "freq"
+ atrace_categories: "gfx"
+ atrace_categories: "view"
+ atrace_categories: "webview"
+ atrace_categories: "input"
+ atrace_categories: "hal"
+ atrace_categories: "binder_driver"
+ atrace_categories: "sync"
+ atrace_categories: "workq"
+ atrace_categories: "res"
+
+ }
+ }
+}
+
+data_sources: {
+ config {
+ name: "android.gpu.memory"
+ target_buffer: 0
+ }
+}
+
+data_sources {
+ config {
+ name: "linux.process_stats"
+ target_buffer: 1
+ process_stats_config {
+ proc_stats_poll_ms: 10000
+ }
+ }
+}
+
+data_sources {
+ config {
+ name: "linux.sys_stats"
+ target_buffer: 1
+ sys_stats_config {
+ meminfo_period_ms: 1000
+ meminfo_counters: MEMINFO_MEM_TOTAL
+ meminfo_counters: MEMINFO_MEM_FREE
+ meminfo_counters: MEMINFO_MEM_AVAILABLE
+ meminfo_counters: MEMINFO_BUFFERS
+ meminfo_counters: MEMINFO_CACHED
+ meminfo_counters: MEMINFO_SWAP_CACHED
+ meminfo_counters: MEMINFO_ACTIVE
+ meminfo_counters: MEMINFO_INACTIVE
+ meminfo_counters: MEMINFO_ACTIVE_ANON
+ meminfo_counters: MEMINFO_INACTIVE_ANON
+ meminfo_counters: MEMINFO_ACTIVE_FILE
+ meminfo_counters: MEMINFO_INACTIVE_FILE
+ meminfo_counters: MEMINFO_UNEVICTABLE
+ meminfo_counters: MEMINFO_SWAP_TOTAL
+ meminfo_counters: MEMINFO_SWAP_FREE
+ meminfo_counters: MEMINFO_DIRTY
+ meminfo_counters: MEMINFO_WRITEBACK
+ meminfo_counters: MEMINFO_ANON_PAGES
+ meminfo_counters: MEMINFO_MAPPED
+ meminfo_counters: MEMINFO_SHMEM
+ }
+ }
+}
+
+data_sources: {
+ config: {
+ name: "android.surfaceflinger.frametimeline"
+ }
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java b/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
index 322bd11..81788c2 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
@@ -45,7 +45,7 @@
import java.util.Random;
/**
- * Logger Implementation using Westworld.
+ * Logger Implementation to log to statsd.
*
* <p>This class is thread-safe.
*
@@ -95,7 +95,7 @@
private long mLastPushTimeMillisLocked = 0;
/**
- * Helper class to hold platform specific stats for Westworld.
+ * Helper class to hold platform specific stats for statsd.
*/
static final class ExtraStats {
// UID for the calling package of the stats.
@@ -113,7 +113,7 @@
}
/**
- * Westworld constructor
+ * Constructor
*/
public PlatformLogger(
@NonNull Context userContext,
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index e876a36..a90a0a4 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -333,8 +333,10 @@
method public void clickNotification(@Nullable String, int, int, boolean);
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void collapsePanels();
method public void expandNotificationsPanel();
+ method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void handleSystemKey(int);
method public void sendNotificationFeedback(@Nullable String, @Nullable android.os.Bundle);
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setExpansionDisabledForSimNetworkLock(boolean);
+ method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void togglePanel();
}
public final class SyncNotedAppOp implements android.os.Parcelable {
@@ -1048,8 +1050,16 @@
package android.hardware {
public final class SensorPrivacyManager {
- method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacy(int, boolean);
- method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacyForProfileGroup(int, boolean);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacy(int, int, boolean);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacyForProfileGroup(int, int, boolean);
+ }
+
+ public static class SensorPrivacyManager.Sources {
+ field public static final int DIALOG = 3; // 0x3
+ field public static final int OTHER = 5; // 0x5
+ field public static final int QS_TILE = 1; // 0x1
+ field public static final int SETTINGS = 2; // 0x2
+ field public static final int SHELL = 4; // 0x4
}
}
@@ -2386,6 +2396,7 @@
package android.speech {
public class SpeechRecognizer {
+ method @MainThread @NonNull public static android.speech.SpeechRecognizer createOnDeviceTestingSpeechRecognizer(@NonNull android.content.Context);
method @RequiresPermission(android.Manifest.permission.MANAGE_SPEECH_RECOGNITION) public void setTemporaryOnDeviceRecognizer(@Nullable android.content.ComponentName);
}
diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java
index 633b986..bd43868 100644
--- a/core/java/android/app/ActivityClient.java
+++ b/core/java/android/app/ActivityClient.java
@@ -431,19 +431,6 @@
}
}
- /**
- * Restart the process and activity to adopt the latest configuration for size compat mode.
- * This only takes effect for visible activity because invisible background activity can be
- * restarted naturally when it becomes visible.
- */
- public void restartActivityProcessIfVisible(IBinder token) {
- try {
- getActivityClientController().restartActivityProcessIfVisible(token);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- }
-
/** Removes the snapshot of home task. */
public void invalidateHomeTaskSnapshot(IBinder homeToken) {
try {
diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl
index 09b0c2f..c664969 100644
--- a/core/java/android/app/IActivityClientController.aidl
+++ b/core/java/android/app/IActivityClientController.aidl
@@ -117,16 +117,6 @@
oneway void setDisablePreviewScreenshots(in IBinder token, boolean disable);
/**
- * Restarts the activity by killing its process if it is visible. If the activity is not
- * visible, the activity will not be restarted immediately and just keep the activity record in
- * the stack. It also resets the current override configuration so the activity will use the
- * configuration according to the latest state.
- *
- * @param activityToken The token of the target activity to restart.
- */
- void restartActivityProcessIfVisible(in IBinder activityToken);
-
- /**
* It should only be called from home activity to remove its outdated snapshot. The home
* snapshot is used to speed up entering home from screen off. If the content of home activity
* is significantly different from before taking the snapshot, then the home activity can use
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 232b077..77bcef3 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -352,6 +352,42 @@
}
/**
+ * Toggles the notification panel.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.STATUS_BAR)
+ @TestApi
+ public void togglePanel() {
+ try {
+ final IStatusBarService svc = getService();
+ if (svc != null) {
+ svc.togglePanel();
+ }
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Sends system keys to the status bar.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.STATUS_BAR)
+ @TestApi
+ public void handleSystemKey(int key) {
+ try {
+ final IStatusBarService svc = getService();
+ if (svc != null) {
+ svc.handleSystemKey(key);
+ }
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Expand the settings panel.
*
* @hide
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index b95412f..444cc4e 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -187,13 +187,6 @@
public ActivityInfo topActivityInfo;
/**
- * The top activity in this task.
- * @hide
- */
- @Nullable
- public IBinder topActivityToken;
-
- /**
* Whether the direct top activity is in size compat mode on foreground.
* @hide
*/
@@ -356,12 +349,12 @@
return displayId == that.displayId
&& taskId == that.taskId
&& topActivityInSizeCompat == that.topActivityInSizeCompat
- // TopActivityToken and bounds are important if top activity is in size compat
- && (!topActivityInSizeCompat || topActivityToken.equals(that.topActivityToken))
+ // Bounds are important if top activity is in size compat
&& (!topActivityInSizeCompat || configuration.windowConfiguration.getBounds()
.equals(that.configuration.windowConfiguration.getBounds()))
&& (!topActivityInSizeCompat || configuration.getLayoutDirection()
- == that.configuration.getLayoutDirection());
+ == that.configuration.getLayoutDirection())
+ && (!topActivityInSizeCompat || isVisible == that.isVisible);
}
/**
@@ -396,7 +389,6 @@
parentTaskId = source.readInt();
isFocused = source.readBoolean();
isVisible = source.readBoolean();
- topActivityToken = source.readStrongBinder();
topActivityInSizeCompat = source.readBoolean();
mTopActivityLocusId = source.readTypedObject(LocusId.CREATOR);
}
@@ -434,7 +426,6 @@
dest.writeInt(parentTaskId);
dest.writeBoolean(isFocused);
dest.writeBoolean(isVisible);
- dest.writeStrongBinder(topActivityToken);
dest.writeBoolean(topActivityInSizeCompat);
dest.writeTypedObject(mTopActivityLocusId, flags);
}
@@ -462,7 +453,6 @@
+ " parentTaskId=" + parentTaskId
+ " isFocused=" + isFocused
+ " isVisible=" + isVisible
- + " topActivityToken=" + topActivityToken
+ " topActivityInSizeCompat=" + topActivityInSizeCompat
+ " locusId= " + mTopActivityLocusId
+ "}";
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 421b4de9..f5ab2ab 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -120,6 +120,7 @@
*/
public final class BluetoothAdapter {
private static final String TAG = "BluetoothAdapter";
+ private static final String DESCRIPTOR = "android.bluetooth.BluetoothAdapter";
private static final boolean DBG = true;
private static final boolean VDBG = false;
@@ -805,7 +806,7 @@
mManagerService = Objects.requireNonNull(managerService);
mAttributionSource = Objects.requireNonNull(attributionSource);
mLeScanClients = new HashMap<LeScanCallback, ScanCallback>();
- mToken = new Binder();
+ mToken = new Binder(DESCRIPTOR);
}
/**
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index 1dda637..c499f69 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -86,6 +86,8 @@
*/
@Immutable
public final class AttributionSource implements Parcelable {
+ private static final String DESCRIPTOR = "android.content.AttributionSource";
+
private final @NonNull AttributionSourceState mAttributionSourceState;
private @Nullable AttributionSource mNextCached;
@@ -95,7 +97,7 @@
@TestApi
public AttributionSource(int uid, @Nullable String packageName,
@Nullable String attributionTag) {
- this(uid, packageName, attributionTag, new Binder());
+ this(uid, packageName, attributionTag, new Binder(DESCRIPTOR));
}
/** @hide */
@@ -130,7 +132,7 @@
AttributionSource(int uid, @Nullable String packageName, @Nullable String attributionTag,
@Nullable String[] renouncedPermissions, @Nullable AttributionSource next) {
- this(uid, packageName, attributionTag, new Binder(), renouncedPermissions, next);
+ this(uid, packageName, attributionTag, new Binder(DESCRIPTOR), renouncedPermissions, next);
}
AttributionSource(int uid, @Nullable String packageName, @Nullable String attributionTag,
@@ -541,7 +543,7 @@
if ((mBuilderFieldsSet & 0x10) == 0) {
mAttributionSourceState.next = null;
}
- mAttributionSourceState.token = new Binder();
+ mAttributionSourceState.token = new Binder(DESCRIPTOR);
if (mAttributionSourceState.next == null) {
// The NDK aidl backend doesn't support null parcelable arrays.
mAttributionSourceState.next = new AttributionSourceState[0];
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 60ab83a..95c5612 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1363,7 +1363,8 @@
public boolean alwaysSandboxDisplayApis() {
return CompatChanges.isChangeEnabled(ALWAYS_SANDBOX_DISPLAY_APIS,
applicationInfo.packageName,
- UserHandle.getUserHandleForUid(applicationInfo.uid));
+ UserHandle.getUserHandleForUid(applicationInfo.uid))
+ || ConstrainDisplayApisConfig.alwaysConstrainDisplayApis(applicationInfo);
}
/** @hide */
diff --git a/core/java/android/content/pm/ConstrainDisplayApisConfig.java b/core/java/android/content/pm/ConstrainDisplayApisConfig.java
index 1337347..11ba3d4 100644
--- a/core/java/android/content/pm/ConstrainDisplayApisConfig.java
+++ b/core/java/android/content/pm/ConstrainDisplayApisConfig.java
@@ -47,6 +47,14 @@
"never_constrain_display_apis_all_packages";
/**
+ * A string flag whose value holds a comma separated list of package entries in the format
+ * '<package-name>:<min-version-code>?:<max-version-code>?' for which Display APIs should
+ * always be constrained.
+ */
+ private static final String FLAG_ALWAYS_CONSTRAIN_DISPLAY_APIS =
+ "always_constrain_display_apis";
+
+ /**
* Returns true if either the flag 'never_constrain_display_apis_all_packages' is true or the
* flag 'never_constrain_display_apis' contains a package entry that matches the given {@code
* applicationInfo}.
@@ -58,8 +66,30 @@
FLAG_NEVER_CONSTRAIN_DISPLAY_APIS_ALL_PACKAGES, /* defaultValue= */ false)) {
return true;
}
+
+ return flagHasMatchingPackageEntry(FLAG_NEVER_CONSTRAIN_DISPLAY_APIS, applicationInfo);
+ }
+
+ /**
+ * Returns true if the flag 'always_constrain_display_apis' contains a package entry that
+ * matches the given {@code applicationInfo}.
+ *
+ * @param applicationInfo Information about the application/package.
+ */
+ public static boolean alwaysConstrainDisplayApis(ApplicationInfo applicationInfo) {
+ return flagHasMatchingPackageEntry(FLAG_ALWAYS_CONSTRAIN_DISPLAY_APIS, applicationInfo);
+ }
+
+ /**
+ * Returns true if the flag with the given {@code flagName} contains a package entry that
+ * matches the given {@code applicationInfo}.
+ *
+ * @param applicationInfo Information about the application/package.
+ */
+ private static boolean flagHasMatchingPackageEntry(String flagName,
+ ApplicationInfo applicationInfo) {
String configStr = DeviceConfig.getString(NAMESPACE_CONSTRAIN_DISPLAY_APIS,
- FLAG_NEVER_CONSTRAIN_DISPLAY_APIS, /* defaultValue= */ "");
+ flagName, /* defaultValue= */ "");
// String#split returns a non-empty array given an empty string.
if (configStr.isEmpty()) {
diff --git a/core/java/android/hardware/ISensorPrivacyManager.aidl b/core/java/android/hardware/ISensorPrivacyManager.aidl
index 1c8e959..6105c26 100644
--- a/core/java/android/hardware/ISensorPrivacyManager.aidl
+++ b/core/java/android/hardware/ISensorPrivacyManager.aidl
@@ -41,9 +41,9 @@
void setSensorPrivacy(boolean enable);
- void setIndividualSensorPrivacy(int userId, int sensor, boolean enable);
+ void setIndividualSensorPrivacy(int userId, int source, int sensor, boolean enable);
- void setIndividualSensorPrivacyForProfileGroup(int userId, int sensor, boolean enable);
+ void setIndividualSensorPrivacyForProfileGroup(int userId, int source, int sensor, boolean enable);
// =============== End of transactions used on native side as well ============================
void suppressIndividualSensorPrivacyReminders(int userId, String packageName, IBinder token,
diff --git a/core/java/android/hardware/SensorPrivacyManager.java b/core/java/android/hardware/SensorPrivacyManager.java
index 1a5e5a8..c392fbb 100644
--- a/core/java/android/hardware/SensorPrivacyManager.java
+++ b/core/java/android/hardware/SensorPrivacyManager.java
@@ -30,6 +30,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.service.SensorPrivacyIndividualEnabledSensorProto;
+import android.service.SensorPrivacyToggleSourceProto;
import android.util.ArrayMap;
import android.util.Pair;
import android.util.SparseArray;
@@ -41,11 +42,7 @@
import java.util.concurrent.Executor;
/**
- * This class provides access to the sensor privacy services; sensor privacy allows the
- * user to disable access to all sensors on the device. This class provides methods to query the
- * current state of sensor privacy as well as to register / unregister for notification when
- * the sensor privacy state changes.
- *
+ * This class provides information about the microphone and camera toggles.
*/
@SystemService(Context.SENSOR_PRIVACY_SERVICE)
public final class SensorPrivacyManager {
@@ -103,6 +100,56 @@
}
/**
+ * Source through which Privacy Sensor was toggled.
+ * @hide
+ */
+ @TestApi
+ public static class Sources {
+ private Sources() {}
+
+ /**
+ * Constant for the Quick Setting Tile.
+ */
+ public static final int QS_TILE = SensorPrivacyToggleSourceProto.QS_TILE;
+
+ /**
+ * Constant for the Settings.
+ */
+ public static final int SETTINGS = SensorPrivacyToggleSourceProto.SETTINGS;
+
+ /**
+ * Constant for Dialog.
+ */
+ public static final int DIALOG = SensorPrivacyToggleSourceProto.DIALOG;
+
+ /**
+ * Constant for SHELL.
+ */
+ public static final int SHELL = SensorPrivacyToggleSourceProto.SHELL;
+
+ /**
+ * Constant for OTHER.
+ */
+ public static final int OTHER = SensorPrivacyToggleSourceProto.OTHER;
+
+ /**
+ * Source for toggling sensors
+ *
+ * @hide
+ */
+ @IntDef(value = {
+ QS_TILE,
+ SETTINGS,
+ DIALOG,
+ SHELL,
+ OTHER
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Source {}
+
+ }
+
+ /**
* A class implementing this interface can register with the {@link
* android.hardware.SensorPrivacyManager} to receive notification when the sensor privacy
* state changes.
@@ -343,8 +390,9 @@
*/
@TestApi
@RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
- public void setSensorPrivacy(@Sensors.Sensor int sensor, boolean enable) {
- setSensorPrivacy(sensor, enable, mContext.getUserId());
+ public void setSensorPrivacy(@Sources.Source int source, @Sensors.Sensor int sensor,
+ boolean enable) {
+ setSensorPrivacy(source, sensor, enable, mContext.getUserId());
}
/**
@@ -357,10 +405,10 @@
* @hide
*/
@RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
- public void setSensorPrivacy(@Sensors.Sensor int sensor, boolean enable,
- @UserIdInt int userId) {
+ public void setSensorPrivacy(@Sources.Source int source, @Sensors.Sensor int sensor,
+ boolean enable, @UserIdInt int userId) {
try {
- mService.setIndividualSensorPrivacy(userId, sensor, enable);
+ mService.setIndividualSensorPrivacy(userId, source, sensor, enable);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -370,6 +418,7 @@
* Sets sensor privacy to the specified state for an individual sensor for the profile group of
* context's user.
*
+ * @param source the source using which the sensor is toggled.
* @param sensor the sensor which to change the state for
* @param enable the state to which sensor privacy should be set.
*
@@ -377,15 +426,16 @@
*/
@TestApi
@RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
- public void setSensorPrivacyForProfileGroup(@Sensors.Sensor int sensor,
- boolean enable) {
- setSensorPrivacyForProfileGroup(sensor, enable, mContext.getUserId());
+ public void setSensorPrivacyForProfileGroup(@Sources.Source int source,
+ @Sensors.Sensor int sensor, boolean enable) {
+ setSensorPrivacyForProfileGroup(source , sensor, enable, mContext.getUserId());
}
/**
* Sets sensor privacy to the specified state for an individual sensor for the profile group of
* context's user.
*
+ * @param source the source using which the sensor is toggled.
* @param sensor the sensor which to change the state for
* @param enable the state to which sensor privacy should be set.
* @param userId the user's id
@@ -393,11 +443,10 @@
* @hide
*/
@RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
- public void setSensorPrivacyForProfileGroup(@Sensors.Sensor int sensor,
- boolean enable, @UserIdInt int userId) {
+ public void setSensorPrivacyForProfileGroup(@Sources.Source int source,
+ @Sensors.Sensor int sensor, boolean enable, @UserIdInt int userId) {
try {
- mService.setIndividualSensorPrivacyForProfileGroup(userId, sensor,
- enable);
+ mService.setIndividualSensorPrivacyForProfileGroup(userId, source, sensor, enable);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 906256d..c78dd53 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -2289,6 +2289,16 @@
* {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} is not 1.0, and {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} is set to be
* windowboxing, the camera framework will override the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} to be
* the active array.</p>
+ * <p>In the capture request, if the application sets {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} to a
+ * value != 1.0, the {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} tag in the capture result reflects the
+ * effective zoom ratio achieved by the camera device, and the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}
+ * adjusts for additional crops that are not zoom related. Otherwise, if the application
+ * sets {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} to 1.0, or does not set it at all, the
+ * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} tag in the result metadata will also be 1.0.</p>
+ * <p>When the application requests a physical stream for a logical multi-camera, the
+ * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} in the physical camera result metadata will be 1.0, and
+ * the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} tag reflects the amount of zoom and crop done by the
+ * physical camera device.</p>
* <p><b>Range of valid values:</b><br>
* {@link CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE android.control.zoomRatioRange}</p>
* <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index d32341f..296bfbe 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2567,6 +2567,16 @@
* {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} is not 1.0, and {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} is set to be
* windowboxing, the camera framework will override the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} to be
* the active array.</p>
+ * <p>In the capture request, if the application sets {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} to a
+ * value != 1.0, the {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} tag in the capture result reflects the
+ * effective zoom ratio achieved by the camera device, and the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}
+ * adjusts for additional crops that are not zoom related. Otherwise, if the application
+ * sets {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} to 1.0, or does not set it at all, the
+ * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} tag in the result metadata will also be 1.0.</p>
+ * <p>When the application requests a physical stream for a logical multi-camera, the
+ * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} in the physical camera result metadata will be 1.0, and
+ * the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} tag reflects the amount of zoom and crop done by the
+ * physical camera device.</p>
* <p><b>Range of valid values:</b><br>
* {@link CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE android.control.zoomRatioRange}</p>
* <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 2e841f5..09fe102 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -1869,26 +1869,40 @@
@FastNative
private static native void nativeUpdate(long dst, long src);
- private static synchronized native void nativeWriteToParcel(Parcel dest, long ptr);
- private static synchronized native void nativeReadFromParcel(Parcel source, long ptr);
- private static synchronized native void nativeSwap(long ptr, long otherPtr)
+ @FastNative
+ private static native void nativeWriteToParcel(Parcel dest, long ptr);
+ @FastNative
+ private static native void nativeReadFromParcel(Parcel source, long ptr);
+ @FastNative
+ private static native void nativeSwap(long ptr, long otherPtr)
throws NullPointerException;
- private static synchronized native void nativeClose(long ptr);
- private static synchronized native boolean nativeIsEmpty(long ptr);
- private static synchronized native int nativeGetEntryCount(long ptr);
- private static synchronized native long nativeGetBufferSize(long ptr);
+ @FastNative
+ private static native void nativeClose(long ptr);
+ @FastNative
+ private static native boolean nativeIsEmpty(long ptr);
+ @FastNative
+ private static native int nativeGetEntryCount(long ptr);
+ @FastNative
+ private static native long nativeGetBufferSize(long ptr);
+ @FastNative
+ private static native void nativeSetVendorId(long ptr, long vendorId);
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private static synchronized native byte[] nativeReadValues(int tag, long ptr);
- private static synchronized native void nativeWriteValues(int tag, byte[] src, long ptr);
+ @FastNative
+ private static native byte[] nativeReadValues(int tag, long ptr);
+ @FastNative
+ private static native void nativeWriteValues(int tag, byte[] src, long ptr);
private static synchronized native void nativeDump(long ptr) throws IOException; // dump to LOGD
- private static synchronized native ArrayList nativeGetAllVendorKeys(long ptr, Class keyClass);
+ @FastNative
+ private static native ArrayList nativeGetAllVendorKeys(long ptr, Class keyClass);
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private static synchronized native int nativeGetTagFromKeyLocal(long ptr, String keyName)
+ @FastNative
+ private static native int nativeGetTagFromKeyLocal(long ptr, String keyName)
throws IllegalArgumentException;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private static synchronized native int nativeGetTypeFromTagLocal(long ptr, int tag)
+ @FastNative
+ private static native int nativeGetTypeFromTagLocal(long ptr, int tag)
throws IllegalArgumentException;
@FastNative
private static native int nativeGetTagFromKey(String keyName, long vendorId)
@@ -1917,6 +1931,15 @@
}
/**
+ * Set the native metadata vendor id.
+ *
+ * @hide
+ */
+ public void setVendorId(long vendorId) {
+ nativeSetVendorId(mMetadataPtr, vendorId);
+ }
+
+ /**
* @hide
*/
public int getEntryCount() {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a6332d7..6b2123d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8748,6 +8748,7 @@
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@TestApi
+ @Readable
public static final String NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component";
/**
diff --git a/core/java/android/service/voice/HotwordDetectedResult.java b/core/java/android/service/voice/HotwordDetectedResult.java
index 5c66021..7234145 100644
--- a/core/java/android/service/voice/HotwordDetectedResult.java
+++ b/core/java/android/service/voice/HotwordDetectedResult.java
@@ -89,6 +89,12 @@
/** Represents unset value for the triggered audio channel. */
public static final int AUDIO_CHANNEL_UNSET = -1;
+ /** Limits the max value for the hotword offset. */
+ private static final int LIMIT_HOTWORD_OFFSET_MAX_VALUE = 60 * 60 * 1000; // 1 hour
+
+ /** Limits the max value for the triggered audio channel. */
+ private static final int LIMIT_AUDIO_CHANNEL_MAX_VALUE = 63;
+
/** Confidence level in the trigger outcome. */
@HotwordConfidenceLevelValue
private final int mConfidenceLevel;
@@ -107,6 +113,8 @@
/**
* Offset in milliseconds the audio stream when the trigger event happened (end of hotword
* phrase).
+ *
+ * <p>Only value between 0 and 3600000 (inclusive) is accepted.
*/
private int mHotwordOffsetMillis = HOTWORD_OFFSET_UNSET;
@@ -118,7 +126,11 @@
*/
private int mHotwordDurationMillis = 0;
- /** Audio channel containing the highest-confidence hotword signal. **/
+ /**
+ * Audio channel containing the highest-confidence hotword signal.
+ *
+ * <p>Only value between 0 and 63 (inclusive) is accepted.
+ */
private int mAudioChannel = AUDIO_CHANNEL_UNSET;
/**
@@ -249,13 +261,13 @@
totalBits += bitCount(CONFIDENCE_LEVEL_VERY_HIGH);
}
if (hotwordDetectedResult.getHotwordOffsetMillis() != HOTWORD_OFFSET_UNSET) {
- totalBits += Integer.SIZE;
+ totalBits += bitCount(LIMIT_HOTWORD_OFFSET_MAX_VALUE);
}
if (hotwordDetectedResult.getHotwordDurationMillis() != 0) {
totalBits += bitCount(AudioRecord.getMaxSharedAudioHistoryMillis());
}
if (hotwordDetectedResult.getAudioChannel() != AUDIO_CHANNEL_UNSET) {
- totalBits += Integer.SIZE;
+ totalBits += bitCount(LIMIT_AUDIO_CHANNEL_MAX_VALUE);
}
// Add one bit for HotwordDetectionPersonalized
@@ -294,6 +306,14 @@
"hotwordPhraseId");
Preconditions.checkArgumentInRange((long) mHotwordDurationMillis, 0,
AudioRecord.getMaxSharedAudioHistoryMillis(), "hotwordDurationMillis");
+ if (mHotwordOffsetMillis != HOTWORD_OFFSET_UNSET) {
+ Preconditions.checkArgumentInRange(mHotwordOffsetMillis, 0,
+ LIMIT_HOTWORD_OFFSET_MAX_VALUE, "hotwordOffsetMillis");
+ }
+ if (mAudioChannel != AUDIO_CHANNEL_UNSET) {
+ Preconditions.checkArgumentInRange(mAudioChannel, 0, LIMIT_AUDIO_CHANNEL_MAX_VALUE,
+ "audioChannel");
+ }
if (!mExtras.isEmpty()) {
Preconditions.checkArgumentInRange(getParcelableSize(mExtras), 0, getMaxBundleSize(),
"extras");
@@ -351,6 +371,27 @@
}
}
+ /** @hide */
+ @IntDef(prefix = "LIMIT_", value = {
+ LIMIT_HOTWORD_OFFSET_MAX_VALUE,
+ LIMIT_AUDIO_CHANNEL_MAX_VALUE
+ })
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
+ @DataClass.Generated.Member
+ /* package-private */ @interface Limit {}
+
+ /** @hide */
+ @DataClass.Generated.Member
+ /* package-private */ static String limitToString(@Limit int value) {
+ switch (value) {
+ case LIMIT_HOTWORD_OFFSET_MAX_VALUE:
+ return "LIMIT_HOTWORD_OFFSET_MAX_VALUE";
+ case LIMIT_AUDIO_CHANNEL_MAX_VALUE:
+ return "LIMIT_AUDIO_CHANNEL_MAX_VALUE";
+ default: return Integer.toHexString(value);
+ }
+ }
+
@DataClass.Generated.Member
/* package-private */ HotwordDetectedResult(
@HotwordConfidenceLevelValue int confidenceLevel,
@@ -392,6 +433,8 @@
/**
* Offset in milliseconds the audio stream when the trigger event happened (end of hotword
* phrase).
+ *
+ * <p>Only value between 0 and 3600000 (inclusive) is accepted.
*/
@DataClass.Generated.Member
public int getHotwordOffsetMillis() {
@@ -410,7 +453,9 @@
}
/**
- * Audio channel containing the highest-confidence hotword signal. *
+ * Audio channel containing the highest-confidence hotword signal.
+ *
+ * <p>Only value between 0 and 63 (inclusive) is accepted.
*/
@DataClass.Generated.Member
public int getAudioChannel() {
@@ -667,6 +712,8 @@
/**
* Offset in milliseconds the audio stream when the trigger event happened (end of hotword
* phrase).
+ *
+ * <p>Only value between 0 and 3600000 (inclusive) is accepted.
*/
@DataClass.Generated.Member
public @NonNull Builder setHotwordOffsetMillis(int value) {
@@ -691,7 +738,9 @@
}
/**
- * Audio channel containing the highest-confidence hotword signal. *
+ * Audio channel containing the highest-confidence hotword signal.
+ *
+ * <p>Only value between 0 and 63 (inclusive) is accepted.
*/
@DataClass.Generated.Member
public @NonNull Builder setAudioChannel(int value) {
@@ -833,10 +882,10 @@
}
@DataClass.Generated(
- time = 1625198973370L,
+ time = 1625541522353L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/service/voice/HotwordDetectedResult.java",
- inputSignatures = "public static final int CONFIDENCE_LEVEL_NONE\npublic static final int CONFIDENCE_LEVEL_LOW\npublic static final int CONFIDENCE_LEVEL_LOW_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final int CONFIDENCE_LEVEL_HIGH\npublic static final int CONFIDENCE_LEVEL_VERY_HIGH\npublic static final int HOTWORD_OFFSET_UNSET\npublic static final int AUDIO_CHANNEL_UNSET\nprivate final @android.service.voice.HotwordDetectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate @android.annotation.Nullable android.media.MediaSyncEvent mMediaSyncEvent\nprivate int mHotwordOffsetMillis\nprivate int mHotwordDurationMillis\nprivate int mAudioChannel\nprivate boolean mHotwordDetectionPersonalized\nprivate final int mScore\nprivate final int mPersonalizedScore\nprivate final int mHotwordPhraseId\nprivate final @android.annotation.NonNull android.os.PersistableBundle mExtras\nprivate static int sMaxBundleSize\nprivate static int defaultConfidenceLevel()\nprivate static int defaultScore()\nprivate static int defaultPersonalizedScore()\npublic static int getMaxScore()\nprivate static int defaultHotwordPhraseId()\npublic static int getMaxHotwordPhraseId()\nprivate static android.os.PersistableBundle defaultExtras()\npublic static int getMaxBundleSize()\npublic @android.annotation.Nullable android.media.MediaSyncEvent getMediaSyncEvent()\npublic static int getParcelableSize(android.os.Parcelable)\npublic static int getUsageSize(android.service.voice.HotwordDetectedResult)\nprivate static int bitCount(long)\nprivate void onConstructed()\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
+ inputSignatures = "public static final int CONFIDENCE_LEVEL_NONE\npublic static final int CONFIDENCE_LEVEL_LOW\npublic static final int CONFIDENCE_LEVEL_LOW_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final int CONFIDENCE_LEVEL_HIGH\npublic static final int CONFIDENCE_LEVEL_VERY_HIGH\npublic static final int HOTWORD_OFFSET_UNSET\npublic static final int AUDIO_CHANNEL_UNSET\nprivate static final int LIMIT_HOTWORD_OFFSET_MAX_VALUE\nprivate static final int LIMIT_AUDIO_CHANNEL_MAX_VALUE\nprivate final @android.service.voice.HotwordDetectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate @android.annotation.Nullable android.media.MediaSyncEvent mMediaSyncEvent\nprivate int mHotwordOffsetMillis\nprivate int mHotwordDurationMillis\nprivate int mAudioChannel\nprivate boolean mHotwordDetectionPersonalized\nprivate final int mScore\nprivate final int mPersonalizedScore\nprivate final int mHotwordPhraseId\nprivate final @android.annotation.NonNull android.os.PersistableBundle mExtras\nprivate static int sMaxBundleSize\nprivate static int defaultConfidenceLevel()\nprivate static int defaultScore()\nprivate static int defaultPersonalizedScore()\npublic static int getMaxScore()\nprivate static int defaultHotwordPhraseId()\npublic static int getMaxHotwordPhraseId()\nprivate static android.os.PersistableBundle defaultExtras()\npublic static int getMaxBundleSize()\npublic @android.annotation.Nullable android.media.MediaSyncEvent getMediaSyncEvent()\npublic static int getParcelableSize(android.os.Parcelable)\npublic static int getUsageSize(android.service.voice.HotwordDetectedResult)\nprivate static int bitCount(long)\nprivate void onConstructed()\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java
index 94da93e..3cdd8b8 100644
--- a/core/java/android/speech/SpeechRecognizer.java
+++ b/core/java/android/speech/SpeechRecognizer.java
@@ -260,23 +260,7 @@
ComponentName componentName =
ComponentName.unflattenFromString(
context.getString(R.string.config_defaultOnDeviceSpeechRecognitionService));
- if (componentName == null) {
- return false;
- }
-
- List<ResolveInfo> resolveInfos =
- context.getPackageManager().queryIntentServices(
- new Intent(RecognitionService.SERVICE_INTERFACE), 0);
- if (resolveInfos == null) {
- return false;
- }
-
- for (ResolveInfo ri : resolveInfos) {
- if (ri.serviceInfo != null && componentName.equals(ri.serviceInfo.getComponentName())) {
- return true;
- }
- }
- return false;
+ return componentName != null;
}
/**
@@ -354,20 +338,41 @@
* notifications will be received.
*
* @param context in which to create {@code SpeechRecognizer}
- * @throws UnsupportedOperationException iff {@link #isOnDeviceRecognitionAvailable(Context)}
- * is false
* @return a new on-device {@code SpeechRecognizer}.
+ * @throws UnsupportedOperationException iff {@link #isOnDeviceRecognitionAvailable(Context)}
+ * is false
*/
@NonNull
@MainThread
public static SpeechRecognizer createOnDeviceSpeechRecognizer(@NonNull final Context context) {
+ if (!isOnDeviceRecognitionAvailable(context)) {
+ throw new UnsupportedOperationException("On-device recognition is not available");
+ }
+ return lenientlyCreateOnDeviceSpeechRecognizer(context);
+ }
+
+ /**
+ * Helper method to create on-device SpeechRecognizer in tests even when the device does not
+ * support on-device speech recognition.
+ *
+ * @hide
+ */
+ @TestApi
+ @NonNull
+ @MainThread
+ public static SpeechRecognizer createOnDeviceTestingSpeechRecognizer(
+ @NonNull final Context context) {
+ return lenientlyCreateOnDeviceSpeechRecognizer(context);
+ }
+
+ @NonNull
+ @MainThread
+ private static SpeechRecognizer lenientlyCreateOnDeviceSpeechRecognizer(
+ @NonNull final Context context) {
if (context == null) {
throw new IllegalArgumentException("Context cannot be null");
}
checkIsCalledFromMainThread();
- if (!isOnDeviceRecognitionAvailable(context)) {
- throw new UnsupportedOperationException("On-device recognition is not available");
- }
return new SpeechRecognizer(context, /* onDevice */ true);
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index c03db6d..4e2f37f 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -234,6 +234,7 @@
private static native long nativeCreateJankDataListenerWrapper(OnJankDataListener listener);
private static native int nativeGetGPUContextPriority();
private static native void nativeSetTransformHint(long nativeObject, int transformHint);
+ private static native int nativeGetTransformHint(long nativeObject);
@Nullable
@GuardedBy("mLock")
@@ -608,7 +609,6 @@
mName = other.mName;
mWidth = other.mWidth;
mHeight = other.mHeight;
- mTransformHint = other.mTransformHint;
mLocalOwnerView = other.mLocalOwnerView;
assignNativeObject(nativeCopyFromSurfaceControl(other.mNativeObject), callsite);
}
@@ -1471,7 +1471,6 @@
mName = in.readString8();
mWidth = in.readInt();
mHeight = in.readInt();
- mTransformHint = in.readInt();
long object = 0;
if (in.readInt() != 0) {
@@ -1490,7 +1489,6 @@
dest.writeString8(mName);
dest.writeInt(mWidth);
dest.writeInt(mHeight);
- dest.writeInt(mTransformHint);
if (mNativeObject == 0) {
dest.writeInt(0);
} else {
@@ -3603,7 +3601,8 @@
* @hide
*/
public int getTransformHint() {
- return mTransformHint;
+ checkNotReleased();
+ return nativeGetTransformHint(mNativeObject);
}
/**
@@ -3616,9 +3615,6 @@
* @hide
*/
public void setTransformHint(@Surface.Rotation int transformHint) {
- if (mTransformHint != transformHint) {
- mTransformHint = transformHint;
- nativeSetTransformHint(mNativeObject, transformHint);
- }
+ nativeSetTransformHint(mNativeObject, transformHint);
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 23faac6..2bd2be1 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -253,6 +253,13 @@
private static final boolean MT_RENDERER_AVAILABLE = true;
/**
+ * Whether or not to report end-to-end input latency. Disabled temporarily as a
+ * risk mitigation against potential jank caused by acquiring a weak reference
+ * per frame
+ */
+ private static final boolean ENABLE_INPUT_LATENCY_TRACKING = false;
+
+ /**
* Set this system property to true to force the view hierarchy to render
* at 60 Hz. This can be used to measure the potential framerate.
*/
@@ -1207,7 +1214,7 @@
mInputEventReceiver = new WindowInputEventReceiver(inputChannel,
Looper.myLooper());
- if (mAttachInfo.mThreadedRenderer != null) {
+ if (ENABLE_INPUT_LATENCY_TRACKING && mAttachInfo.mThreadedRenderer != null) {
InputMetricsListener listener = new InputMetricsListener();
mHardwareRendererObserver = new HardwareRendererObserver(
listener, listener.data, mHandler, true /*waitForPresentTime*/);
diff --git a/core/java/android/window/ITaskOrganizerController.aidl b/core/java/android/window/ITaskOrganizerController.aidl
index 2d0211e..a833600 100644
--- a/core/java/android/window/ITaskOrganizerController.aidl
+++ b/core/java/android/window/ITaskOrganizerController.aidl
@@ -61,4 +61,9 @@
*/
void setInterceptBackPressedOnTaskRoot(in WindowContainerToken task,
boolean interceptBackPressed);
+
+ /**
+ * Restarts the top activity in the given task by killing its process if it is visible.
+ */
+ void restartTaskTopActivityProcessIfVisible(in WindowContainerToken task);
}
diff --git a/core/java/android/window/SplashScreenView.java b/core/java/android/window/SplashScreenView.java
index 148986a..1efd2e3 100644
--- a/core/java/android/window/SplashScreenView.java
+++ b/core/java/android/window/SplashScreenView.java
@@ -133,6 +133,8 @@
private @ColorInt int mIconBackground;
private Bitmap mParceledIconBitmap;
private Drawable mIconDrawable;
+ // It is only set for legacy splash screen which won't be sent across processes.
+ private Drawable mOverlayDrawable;
private SurfaceControlViewHost.SurfacePackage mSurfacePackage;
private RemoteCallback mClientCallback;
private int mBrandingImageWidth;
@@ -193,6 +195,14 @@
}
/**
+ * Set the Drawable object to fill entire view
+ */
+ public Builder setOverlayDrawable(@Nullable Drawable drawable) {
+ mOverlayDrawable = drawable;
+ return this;
+ }
+
+ /**
* Set the Drawable object to fill the center view.
*/
public Builder setCenterViewDrawable(@Nullable Drawable drawable) {
@@ -236,7 +246,11 @@
layoutInflater.inflate(R.layout.splash_screen_view, null, false);
view.mInitBackgroundColor = mBackgroundColor;
view.mInitIconBackgroundColor = mIconBackground;
- view.setBackgroundColor(mBackgroundColor);
+ if (mOverlayDrawable != null) {
+ view.setBackground(mOverlayDrawable);
+ } else {
+ view.setBackgroundColor(mBackgroundColor);
+ }
view.mClientCallback = mClientCallback;
view.mBrandingImageView = view.findViewById(R.id.splashscreen_branding_view);
@@ -261,6 +275,9 @@
}
}
}
+ if (mOverlayDrawable != null || mIconDrawable == null) {
+ view.setNotCopyable();
+ }
if (mParceledIconBitmap != null) {
view.mParceledIconBitmap = mParceledIconBitmap;
diff --git a/core/java/android/window/StartingWindowInfo.java b/core/java/android/window/StartingWindowInfo.java
index 8bc2177..566f154 100644
--- a/core/java/android/window/StartingWindowInfo.java
+++ b/core/java/android/window/StartingWindowInfo.java
@@ -55,6 +55,9 @@
*/
public static final int STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN = 3;
+ /** @hide **/
+ public static final int STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN = 4;
+
/**
* @hide
*/
@@ -62,7 +65,8 @@
STARTING_WINDOW_TYPE_NONE,
STARTING_WINDOW_TYPE_SPLASH_SCREEN,
STARTING_WINDOW_TYPE_SNAPSHOT,
- STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN
+ STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN,
+ STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
})
public @interface StartingWindowType {}
@@ -103,7 +107,8 @@
TYPE_PARAMETER_PROCESS_RUNNING,
TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT,
TYPE_PARAMETER_ACTIVITY_CREATED,
- TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN
+ TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN,
+ TYPE_PARAMETER_LEGACY_SPLASH_SCREEN
})
public @interface StartingTypeParams {}
@@ -122,6 +127,11 @@
public static final int TYPE_PARAMETER_ACTIVITY_CREATED = 0x00000010;
/** @hide */
public static final int TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN = 0x00000020;
+ /**
+ * Application is allowed to use the legacy splash screen
+ * @hide
+ */
+ public static final int TYPE_PARAMETER_LEGACY_SPLASH_SCREEN = 0x80000000;
/**
* The parameters which effect the starting window type.
diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java
index 7399549..c7c91cd 100644
--- a/core/java/android/window/TaskOrganizer.java
+++ b/core/java/android/window/TaskOrganizer.java
@@ -223,6 +223,19 @@
}
/**
+ * Restarts the top activity in the given task by killing its process if it is visible.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
+ public void restartTaskTopActivityProcessIfVisible(@NonNull WindowContainerToken task) {
+ try {
+ mTaskOrganizerController.restartTaskTopActivityProcessIfVisible(task);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Gets the executor to run callbacks on.
* @hide
*/
diff --git a/core/java/com/android/internal/display/BrightnessSynchronizer.java b/core/java/com/android/internal/display/BrightnessSynchronizer.java
index 19183b8..c9a9e51 100644
--- a/core/java/com/android/internal/display/BrightnessSynchronizer.java
+++ b/core/java/com/android/internal/display/BrightnessSynchronizer.java
@@ -154,10 +154,20 @@
}
}
+ /**
+ * Gets the stored screen brightness float value from the display brightness setting.
+ * @return brightness
+ */
private float getScreenBrightnessFloat() {
return mDisplayManager.getBrightness(Display.DEFAULT_DISPLAY);
}
+ /**
+ * Gets the stored screen brightness int from the system settings.
+ * @param context for accessing settings
+ *
+ * @return brightness
+ */
private static int getScreenBrightnessInt(Context context) {
return Settings.System.getIntForUser(context.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS, PowerManager.BRIGHTNESS_INVALID,
diff --git a/core/java/com/android/internal/view/RecyclerViewCaptureHelper.java b/core/java/com/android/internal/view/RecyclerViewCaptureHelper.java
index b29cf1c..848a5ba 100644
--- a/core/java/com/android/internal/view/RecyclerViewCaptureHelper.java
+++ b/core/java/com/android/internal/view/RecyclerViewCaptureHelper.java
@@ -61,77 +61,128 @@
@Override
public ScrollResult onScrollRequested(@NonNull ViewGroup recyclerView, Rect scrollBounds,
Rect requestRect) {
- Log.d(TAG, "-----------------------------------------------------------");
- Log.d(TAG, "onScrollRequested(scrollBounds=" + scrollBounds + ", "
- + "requestRect=" + requestRect + ")");
-
ScrollResult result = new ScrollResult();
result.requestedArea = new Rect(requestRect);
result.scrollDelta = mScrollDelta;
result.availableArea = new Rect(); // empty
+ Log.d(TAG, "current scrollDelta: " + mScrollDelta);
if (!recyclerView.isVisibleToUser() || recyclerView.getChildCount() == 0) {
Log.w(TAG, "recyclerView is empty or not visible, cannot continue");
return result; // result.availableArea == empty Rect
}
- // Make requestRect relative to RecyclerView (from scrollBounds)
- Rect requestedContainerBounds =
- transformFromRequestToContainer(mScrollDelta, scrollBounds, requestRect);
+ // move from scrollBounds-relative to parent-local coordinates
+ Rect requestedContainerBounds = new Rect(requestRect);
+ requestedContainerBounds.offset(0, -mScrollDelta);
+ requestedContainerBounds.offset(scrollBounds.left, scrollBounds.top);
- Rect recyclerLocalVisible = new Rect();
- recyclerView.getLocalVisibleRect(recyclerLocalVisible);
+ // requestedContainerBounds is now in recyclerview-local coordinates
+ Log.d(TAG, "requestedContainerBounds: " + requestedContainerBounds);
- // Expand request rect match visible bounds to center the requested rect vertically
- Rect adjustedContainerBounds = new Rect(requestedContainerBounds);
- int remainingHeight = recyclerLocalVisible.height() - requestedContainerBounds.height();
- if (remainingHeight > 0) {
- adjustedContainerBounds.inset(0, -remainingHeight / 2);
+ // Save a copy for later
+ View anchor = findChildNearestTarget(recyclerView, requestedContainerBounds);
+ if (anchor == null) {
+ Log.d(TAG, "Failed to locate anchor view");
+ return result; // result.availableArea == null
}
- int scrollAmount = computeScrollAmount(recyclerLocalVisible, adjustedContainerBounds);
- if (scrollAmount < 0) {
- Log.d(TAG, "About to scroll UP (content moves down within parent)");
- } else if (scrollAmount > 0) {
- Log.d(TAG, "About to scroll DOWN (content moves up within parent)");
- }
- Log.d(TAG, "scrollAmount: " + scrollAmount);
+ Log.d(TAG, "Anchor view:" + anchor);
+ Rect requestedContentBounds = new Rect(requestedContainerBounds);
+ recyclerView.offsetRectIntoDescendantCoords(anchor, requestedContentBounds);
- View refView = findScrollingReferenceView(recyclerView, scrollAmount);
- int refTop = refView.getTop();
-
- // Map the request into the child view coords
- Rect requestedContentBounds = new Rect(adjustedContainerBounds);
- recyclerView.offsetRectIntoDescendantCoords(refView, requestedContentBounds);
- Log.d(TAG, "request rect, in child view space = " + requestedContentBounds);
-
+ Log.d(TAG, "requestedContentBounds = " + requestedContentBounds);
+ int prevAnchorTop = anchor.getTop();
// Note: requestChildRectangleOnScreen may modify rectangle, must pass pass in a copy here
- Rect request = new Rect(requestedContentBounds);
- recyclerView.requestChildRectangleOnScreen(refView, request, true);
+ Rect input = new Rect(requestedContentBounds);
+ // Expand input rect to get the requested rect to be in the center
+ int remainingHeight = recyclerView.getHeight() - recyclerView.getPaddingTop()
+ - recyclerView.getPaddingBottom() - input.height();
+ if (remainingHeight > 0) {
+ input.inset(0, -remainingHeight / 2);
+ }
+ Log.d(TAG, "input (post center adjustment) = " + input);
- int scrollDistance = refTop - refView.getTop();
- Log.d(TAG, "Parent view scrolled vertically by " + scrollDistance + " px");
-
- mScrollDelta += scrollDistance;
- result.scrollDelta = mScrollDelta;
- if (scrollDistance != 0) {
- Log.d(TAG, "Scroll delta is now " + mScrollDelta + " px");
+ if (recyclerView.requestChildRectangleOnScreen(anchor, input, true)) {
+ int scrolled = prevAnchorTop - anchor.getTop(); // inverse of movement
+ Log.d(TAG, "RecyclerView scrolled by " + scrolled + " px");
+ mScrollDelta += scrolled; // view.top-- is equivalent to parent.scrollY++
+ result.scrollDelta = mScrollDelta;
+ Log.d(TAG, "requestedContentBounds, (post-request-rect) = " + requestedContentBounds);
}
- // Update, post-scroll
- requestedContainerBounds = new Rect(
- transformFromRequestToContainer(mScrollDelta, scrollBounds, requestRect));
+ requestedContainerBounds.set(requestedContentBounds);
+ recyclerView.offsetDescendantRectToMyCoords(anchor, requestedContainerBounds);
+ Log.d(TAG, "requestedContainerBounds, (post-scroll): " + requestedContainerBounds);
- // in case it might have changed (nested scrolling)
+ Rect recyclerLocalVisible = new Rect(scrollBounds);
recyclerView.getLocalVisibleRect(recyclerLocalVisible);
- if (requestedContainerBounds.intersect(recyclerLocalVisible)) {
- result.availableArea = transformFromContainerToRequest(
- mScrollDelta, scrollBounds, requestedContainerBounds);
+ Log.d(TAG, "recyclerLocalVisible: " + recyclerLocalVisible);
+
+ if (!requestedContainerBounds.intersect(recyclerLocalVisible)) {
+ // Requested area is still not visible
+ Log.d(TAG, "requested bounds not visible!");
+ return result;
}
- Log.d(TAG, "-----------------------------------------------------------");
+ Rect available = new Rect(requestedContainerBounds);
+ available.offset(-scrollBounds.left, -scrollBounds.top);
+ available.offset(0, mScrollDelta);
+ result.availableArea = available;
+ Log.d(TAG, "availableArea: " + result.availableArea);
return result;
}
+ /**
+ * Find a view that is located "closest" to targetRect. Returns the first view to fully
+ * vertically overlap the target targetRect. If none found, returns the view with an edge
+ * nearest the target targetRect.
+ *
+ * @param parent the parent vertical layout
+ * @param targetRect a rectangle in local coordinates of <code>parent</code>
+ * @return a child view within parent matching the criteria or null
+ */
+ static View findChildNearestTarget(ViewGroup parent, Rect targetRect) {
+ View selected = null;
+ int minCenterDistance = Integer.MAX_VALUE;
+ int maxOverlap = 0;
+
+ // allowable center-center distance, relative to targetRect.
+ // if within this range, taller views are preferred
+ final float preferredRangeFromCenterPercent = 0.25f;
+ final int preferredDistance =
+ (int) (preferredRangeFromCenterPercent * targetRect.height());
+
+ Rect parentLocalVis = new Rect();
+ parent.getLocalVisibleRect(parentLocalVis);
+ Log.d(TAG, "findChildNearestTarget: parentVis=" + parentLocalVis
+ + " targetRect=" + targetRect);
+
+ Rect frame = new Rect();
+ for (int i = 0; i < parent.getChildCount(); i++) {
+ final View child = parent.getChildAt(i);
+ child.getHitRect(frame);
+ Log.d(TAG, "child #" + i + " hitRect=" + frame);
+
+ if (child.getVisibility() != View.VISIBLE) {
+ Log.d(TAG, "child #" + i + " is not visible");
+ continue;
+ }
+
+ int centerDistance = Math.abs(targetRect.centerY() - frame.centerY());
+ Log.d(TAG, "child #" + i + " : center to center: " + centerDistance + "px");
+
+ if (centerDistance < minCenterDistance) {
+ // closer to center
+ minCenterDistance = centerDistance;
+ selected = child;
+ } else if (frame.intersect(targetRect) && (frame.height() > preferredDistance)) {
+ // within X% pixels of center, but taller
+ selected = child;
+ }
+ }
+ return selected;
+ }
+
@Override
public void onPrepareForEnd(@NonNull ViewGroup view) {
// Restore original position and state
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 4c4c9aa..406ccde 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -690,6 +690,7 @@
char methodTraceFileBuf[sizeof("-Xmethod-trace-file:") + PROPERTY_VALUE_MAX];
char methodTraceFileSizeBuf[sizeof("-Xmethod-trace-file-size:") + PROPERTY_VALUE_MAX];
std::string fingerprintBuf;
+ char javaZygoteForkLoopBuf[sizeof("-XX:ForceJavaZygoteForkLoop=") + PROPERTY_VALUE_MAX];
char jdwpProviderBuf[sizeof("-XjdwpProvider:") - 1 + PROPERTY_VALUE_MAX];
char opaqueJniIds[sizeof("-Xopaque-jni-ids:") - 1 + PROPERTY_VALUE_MAX];
char bootImageBuf[sizeof("-Ximage:") - 1 + PROPERTY_VALUE_MAX];
@@ -913,6 +914,13 @@
parseRuntimeOption("dalvik.vm.backgroundgctype", backgroundgcOptsBuf, "-XX:BackgroundGC=");
/*
+ * Enable/disable zygote native fork loop.
+ */
+ parseRuntimeOption("dalvik.vm.force-java-zygote-fork-loop",
+ javaZygoteForkLoopBuf,
+ "-XX:ForceJavaZygoteForkLoop=");
+
+ /*
* Enable debugging only for apps forked from zygote.
*/
if (zygote) {
diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index 5c9999d..5293c58 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -16,6 +16,7 @@
*/
// #define LOG_NDEBUG 0
+#include <memory>
#define LOG_TAG "CameraMetadata-JNI"
#include <utils/Errors.h>
#include <utils/Log.h>
@@ -162,6 +163,8 @@
extern "C" {
+static void CameraMetadata_setVendorId(JNIEnv* env, jclass thiz, jlong ptr,
+ jlong vendorId);
static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jclass thiz, jlong ptr,
jclass keyType);
static jint CameraMetadata_getTagFromKey(JNIEnv *env, jclass thiz, jstring keyName,
@@ -596,6 +599,9 @@
static const JNINativeMethod gCameraMetadataMethods[] = {
// static methods
+ { "nativeSetVendorId",
+ "(JJ)V",
+ (void *)CameraMetadata_setVendorId },
{ "nativeGetTagFromKey",
"(Ljava/lang/String;J)I",
(void *)CameraMetadata_getTagFromKey },
@@ -870,6 +876,27 @@
return arrayList;
}
+static void CameraMetadata_setVendorId(JNIEnv *env, jclass thiz, jlong ptr,
+ jlong vendorId) {
+ ALOGV("%s", __FUNCTION__);
+
+ CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
+
+ if (metadata == NULL) {
+ ALOGW("%s: Returning early due to exception being thrown",
+ __FUNCTION__);
+ return;
+ }
+ if (metadata->isEmpty()) {
+ std::unique_ptr<CameraMetadata> emptyBuffer = std::make_unique<CameraMetadata>(10);
+ metadata->swap(*emptyBuffer);
+ }
+
+ camera_metadata_t *meta = const_cast<camera_metadata_t *>(metadata->getAndLock());
+ set_camera_metadata_vendor_id(meta, vendorId);
+ metadata->unlock(meta);
+}
+
static jint CameraMetadata_getTagFromKey(JNIEnv *env, jclass thiz, jstring keyName,
jlong vendorId) {
ScopedUtfChars keyScoped(env, keyName);
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index e9e79dc3..1695e1a 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -1785,6 +1785,14 @@
ui::Transform::toRotationFlags(static_cast<ui::Rotation>(transformHint)));
}
+static jint nativeGetTransformHint(JNIEnv* env, jclass clazz, jlong nativeSurfaceControl) {
+ sp<SurfaceControl> surface(reinterpret_cast<SurfaceControl*>(nativeSurfaceControl));
+ ui::Transform::RotationFlags transformHintRotationFlags =
+ static_cast<ui::Transform::RotationFlags>(surface->getTransformHint());
+
+ return toRotationInt(ui::Transform::toRotation((transformHintRotationFlags)));
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod sSurfaceControlMethods[] = {
@@ -1974,6 +1982,8 @@
(void*)nativeGetGPUContextPriority },
{"nativeSetTransformHint", "(JI)V",
(void*)nativeSetTransformHint },
+ {"nativeGetTransformHint", "(J)I",
+ (void*)nativeGetTransformHint },
// clang-format on
};
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 64bf47c..d49d215 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -2602,6 +2602,7 @@
case PR_MTE_TCF_SYNC:
return MEMORY_TAG_LEVEL_SYNC;
case PR_MTE_TCF_ASYNC:
+ case PR_MTE_TCF_ASYNC | PR_MTE_TCF_SYNC:
return MEMORY_TAG_LEVEL_ASYNC;
default:
ALOGE("Unknown memory tagging level: %i", level);
diff --git a/core/proto/android/hardware/sensorprivacy.proto b/core/proto/android/hardware/sensorprivacy.proto
index 401e003..d52af5c 100644
--- a/core/proto/android/hardware/sensorprivacy.proto
+++ b/core/proto/android/hardware/sensorprivacy.proto
@@ -65,4 +65,22 @@
// If sensor privacy is enabled for this sensor
optional bool is_enabled = 2;
+}
+
+message SensorPrivacyToggleSourceProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ enum Source {
+ UNKNOWN = 0;
+
+ QS_TILE = 1;
+ SETTINGS = 2;
+ DIALOG = 3;
+ SHELL = 4;
+ OTHER = 5;
+ }
+
+ // Source for which sensor privacy was toggled.
+ optional Source source = 1;
+
}
\ No newline at end of file
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 6fcef4f..f05e18f 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -610,14 +610,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ফিংগাৰপ্ৰিণ্ট আইকন"</string>
- <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"মুখাৱয়বৰ দ্বাৰা আনলক কৰাৰ সুবিধা"</string>
- <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"মুখাৱয়বৰ দ্বাৰা আনলক কৰাৰ সুবিধাটোৰ ব্যৱহাৰ কৰোঁতে সমস্যা হৈছে"</string>
+ <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ফেচ আনলক"</string>
+ <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ফেচ আনলক ব্যৱহাৰ কৰোঁতে সমস্যা হৈছে"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"আপোনাৰ মুখাৱয়বৰ মডেলটো মচিবলৈ টিপক, তাৰ পাছত পুনৰ আপোনাৰ মুখাৱয়ব যোগ দিয়ক"</string>
- <string name="face_setup_notification_title" msgid="8843461561970741790">"মুখাৱয়বৰে আনলক কৰাৰ সুবিধাটো ছেট আপ কৰক"</string>
+ <string name="face_setup_notification_title" msgid="8843461561970741790">"ফেচ আনলক সুবিধাটো ছেট আপ কৰক"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"আপোনাৰ ফ’নটোলৈ চাই সেইটো আনলক কৰক"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"আনলক কৰাৰ অধিক উপায় ছেট আপ কৰক"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"এটা ফিংগাৰপ্ৰিণ্ট যোগ দিবলৈ টিপক"</string>
- <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"ফিংগাৰপ্ৰিণ্টৰ দ্বাৰা আনলক কৰা সুবিধা"</string>
+ <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"ফিংগাৰপ্ৰিন্ট আনলক"</string>
<string name="fingerprint_recalibrate_notification_title" msgid="2406561052064558497">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰ ব্যৱহাৰ কৰিব নোৱাৰি"</string>
<string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"মেৰামতি সেৱা প্ৰদানকাৰী কোনো প্ৰতিষ্ঠানলৈ যাওক।"</string>
<string name="face_acquired_insufficient" msgid="2150805835949162453">"সঠিক মুখমণ্ডলৰ ডেটা কেপচাৰ নহ’ল। আকৌ চেষ্টা কৰক।"</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"মুখমণ্ডল সত্যাপন কৰিব পৰা নগ’ল। হাৰ্ডৱেৰ নাই।"</string>
- <string name="face_error_timeout" msgid="2598544068593889762">"পুনৰ মুখাৱয়বৰ দ্বাৰা আনলক কৰাটো ব্যৱহাৰ কৰি চাওক"</string>
+ <string name="face_error_timeout" msgid="2598544068593889762">"ফেচ আনলক পুনৰ ব্যৱহাৰ কৰি চাওক"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"নতুন মুখমণ্ডলৰ ডেটা জমা কৰিব পৰা নাই। প্ৰথমে পুৰণি এখন মচক।"</string>
<string name="face_error_canceled" msgid="2164434737103802131">"মুখমণ্ডলৰ প্ৰক্ৰিয়া বাতিল কৰা হ’ল।"</string>
- <string name="face_error_user_canceled" msgid="5766472033202928373">"ব্যৱহাৰকাৰীয়ে মুখাৱয়বৰ দ্বাৰা আনলক কৰাৰ সুবিধাটো বাতিল কৰিছে"</string>
+ <string name="face_error_user_canceled" msgid="5766472033202928373">"ব্যৱহাৰকাৰীয়ে ফেচ আনলক বাতিল কৰিছে"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"অত্যধিক ভুল প্ৰয়াস। কিছুসময়ৰ পাছত আকৌ চেষ্টা কৰক।"</string>
- <string name="face_error_lockout_permanent" msgid="3277134834042995260">"অতি বেছিসংখ্যক প্ৰয়াস। মুখাৱয়বৰ দ্বাৰা আনলক কৰাৰ সুবিধাটো অক্ষম কৰা হৈছে।"</string>
+ <string name="face_error_lockout_permanent" msgid="3277134834042995260">"অতি বেছিসংখ্যক প্ৰয়াস। ফেচ আনলক সুবিধাটো অক্ষম কৰা হৈছে।"</string>
<string name="face_error_lockout_screen_lock" msgid="5062609811636860928">"অতি বেছিসংখ্যক প্ৰয়াস। ইয়াৰ সলনি স্ক্ৰীন লক দিয়ক।"</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"মুখমণ্ডল সত্যাপন কৰিব পৰা নগ’ল। আকৌ চেষ্টা কৰক।"</string>
- <string name="face_error_not_enrolled" msgid="1134739108536328412">"আপুনি মুখাৱয়বৰ দ্বাৰা আনলক কৰাৰ সুবিধাটো ছেট আপ কৰা নাই"</string>
- <string name="face_error_hw_not_present" msgid="7940978724978763011">"এই ডিভাইচটোত মুখাৱয়বৰ দ্বাৰা আনলক কৰাৰ সুবিধাটো সমৰ্থিত নহয়"</string>
+ <string name="face_error_not_enrolled" msgid="1134739108536328412">"ফেচ আনলক সুবিধাটো ছেট আপ কৰা নাই"</string>
+ <string name="face_error_hw_not_present" msgid="7940978724978763011">"এই ডিভাইচটোত ফেচ আনলক সুবিধাটো সমৰ্থিত নহয়"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"ছেন্সৰটো সাময়িকভাৱে অক্ষম হৈ আছে।"</string>
<string name="face_name_template" msgid="3877037340223318119">"মুখমণ্ডল <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="5854024256907828015">"মুখাৱয়বৰে আনলক কৰাটো ব্যৱহাৰ কৰক"</string>
+ <string name="face_app_setting_name" msgid="5854024256907828015">"ফেচ আনলক ব্যৱহাৰ কৰক"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"ফেচ আনলক অথবা স্ক্ৰীন লক ব্যৱহাৰ কৰক"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"অব্যাহত ৰাখিবলৈ নিজৰ মুখাৱয়ব ব্যৱহাৰ কৰক"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"অব্যাহত ৰাখিবলৈ আপোনাৰ মুখাৱয়ব অথবা স্ক্ৰীন লক ব্যৱহাৰ কৰক"</string>
@@ -958,7 +958,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"আনলক ক্ষেত্ৰ বিস্তাৰ কৰক।"</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"শ্লাইডৰদ্বাৰা আনলক।"</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"আৰ্হিৰদ্বাৰা আনলক।"</string>
- <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"মুখাৱয়বৰ দ্বাৰা আনলক কৰাৰ সুবিধা।"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"ফেচ আনলক।"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"পিনৰদ্বাৰা আনলক।"</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"ছিম পিন আনলক।"</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"ছিম পিইউকে আনলক।"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index f58abbd..47bcbe1 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -610,7 +610,7 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"আঙ্গুলের ছাপ আইকন"</string>
- <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"\'ফেস আনলক\'"</string>
+ <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ফেস আনলক"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"\'ফেস আনলক\' ফিচার ব্যবহার করার ক্ষেত্রে হওয়া সমস্যা"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"আপনার ফেস মডেল মুছে দেওয়ার জন্য ট্যাপ করুন এবং তারপরে আবার ফেস যোগ করুন"</string>
<string name="face_setup_notification_title" msgid="8843461561970741790">"\'ফেস আনলক\' সেট আপ করুন"</string>
@@ -958,7 +958,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"আনলক এলাকা প্রসারিত করুন৷"</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"স্লাইড দিয়ে আনলক৷"</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"প্যাটার্ন দিয়ে আনলক৷"</string>
- <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"\'ফেস আনলক\'।"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"ফেস আনলক।"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"পিন দিয়ে আনলক৷"</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"সিম পিন আনলক।"</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"সিম পিইউকে আনলক।"</string>
@@ -1482,8 +1482,7 @@
<string name="deny" msgid="6632259981847676572">"অস্বীকার করুন"</string>
<string name="permission_request_notification_title" msgid="1810025922441048273">"অনুমতির অনুরোধ করা হয়েছে"</string>
<string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"<xliff:g id="ACCOUNT">%s</xliff:g>অ্যাকাউন্টের জন্য\nঅনুমতির অনুরোধ করা হয়েছে৷"</string>
- <!-- no translation found for permission_request_notification_for_app_with_subtitle (1298704005732851350) -->
- <skip />
+ <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"<xliff:g id="ACCOUNT">%2$s</xliff:g> অ্যাকাউন্টের জন্য <xliff:g id="APP">%1$s</xliff:g>\n থেকে অনুমতি চাওয়া হয়েছে।"</string>
<string name="forward_intent_to_owner" msgid="4620359037192871015">"আপনি এই অ্যাপ্লিকেশানটি আপনার কর্মস্থলের প্রোফাইলের বাইরে ব্যবহার করছেন"</string>
<string name="forward_intent_to_work" msgid="3620262405636021151">"আপনি এই অ্যাপ্লিকেশানটি আপনার কর্মস্থলের প্রোফাইলে ব্যবহার করছেন"</string>
<string name="input_method_binding_label" msgid="1166731601721983656">"ইনপুট পদ্ধতি"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 394f074..088495e 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -648,7 +648,7 @@
<string name="face_error_canceled" msgid="2164434737103802131">"Gesichtserkennung abgebrochen."</string>
<string name="face_error_user_canceled" msgid="5766472033202928373">"Entsperrung per Gesichtserkennung vom Nutzer abgebrochen"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Zu viele Versuche, bitte später noch einmal versuchen"</string>
- <string name="face_error_lockout_permanent" msgid="3277134834042995260">"Zu viele Versuche. Entsperrung per Gesichtserkennung wurde deaktiviert."</string>
+ <string name="face_error_lockout_permanent" msgid="3277134834042995260">"Zu viele Versuche. Die Entsperrung per Gesichtserkennung wurde deaktiviert."</string>
<string name="face_error_lockout_screen_lock" msgid="5062609811636860928">"Zu viele Versuche. Verwende stattdessen die Displaysperre."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Gesichtsprüfung nicht möglich. Noch mal versuchen."</string>
<string name="face_error_not_enrolled" msgid="1134739108536328412">"Entsperrung per Gesichtserkennung ist nicht eingerichtet"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index be9e4d7..93c7bc1 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -617,7 +617,7 @@
<string name="face_setup_notification_content" msgid="5463999831057751676">"Desbloquea el teléfono con solo mirarlo"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Configura más formas de desbloqueo"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Toca para añadir una huella digital"</string>
- <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"Desbloqueo con Huella Digital"</string>
+ <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"Desbloqueo con huella digital"</string>
<string name="fingerprint_recalibrate_notification_title" msgid="2406561052064558497">"No se puede usar el sensor de huellas digitales"</string>
<string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Visita un proveedor de reparaciones."</string>
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Datos faciales no reconocidos. Vuelve a intentarlo."</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index baa8da0..d4705c1 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -643,7 +643,7 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Ezin da egiaztatu aurpegia. Hardwarea ez dago erabilgarri."</string>
- <string name="face_error_timeout" msgid="2598544068593889762">"Saiatu berriro aurpegiaren bidez desblokeatzen"</string>
+ <string name="face_error_timeout" msgid="2598544068593889762">"Saiatu berriro aurpegi bidez desblokeatzen"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Ezin dira gorde aurpegiaren datu berriak. Ezabatu zaharrak."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Utzi da aurpegiaren bidezko eragiketa."</string>
<string name="face_error_user_canceled" msgid="5766472033202928373">"Erabiltzaileak aurpegi bidez desblokeatzeko aukera utzi du"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 590cbe2..ea160bc 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1482,8 +1482,7 @@
<string name="deny" msgid="6632259981847676572">"Refuser"</string>
<string name="permission_request_notification_title" msgid="1810025922441048273">"Autorisation demandée"</string>
<string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"Autorisation demandée\npour le compte \"<xliff:g id="ACCOUNT">%s</xliff:g>\""</string>
- <!-- no translation found for permission_request_notification_for_app_with_subtitle (1298704005732851350) -->
- <skip />
+ <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"Autorisation demandée par <xliff:g id="APP">%1$s</xliff:g>\npour le compte <xliff:g id="ACCOUNT">%2$s</xliff:g>."</string>
<string name="forward_intent_to_owner" msgid="4620359037192871015">"Vous utilisez cette application en dehors de votre profil professionnel"</string>
<string name="forward_intent_to_work" msgid="3620262405636021151">"Vous utilisez cette application dans votre profil professionnel"</string>
<string name="input_method_binding_label" msgid="1166731601721983656">"Mode de saisie"</string>
@@ -2100,7 +2099,7 @@
<string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
<string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Désactiver"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"En savoir plus"</string>
- <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Les notifications améliorées ont remplacé les notifications adaptatives Android sous Android 12. Cette fonctionnalité vous présente des suggestions d\'actions et de réponse, et organise vos notifications.\n\nLes notifications améliorées peuvent accéder au contenu de toutes les notifications, y compris les renseignements personnels comme le nom des contacts et les messages. Cette fonctionnalité peut aussi fermer des notifications ou interagir avec elles, comme répondre aux appels téléphoniques et gérer le mode Ne pas déranger."</string>
+ <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Les notifications améliorées ont remplacé les notifications adaptatives Android sous Android 12. Cette fonctionnalité vous présente des suggestions d\'actions et de réponses, et organise vos notifications.\n\nLes notifications améliorées peuvent accéder au contenu de toutes les notifications, y compris les renseignements personnels comme le nom des contacts et les messages. Cette fonctionnalité peut aussi fermer des notifications ou interagir avec elles, comme répondre aux appels téléphoniques et gérer le mode Ne pas déranger."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notification d\'information du mode Routine"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"La pile pourrait s\'épuiser avant la charge habituelle"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Le mode Économiseur de pile est activé afin de prolonger l\'autonomie"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index e71c249..2f8deaf 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -613,7 +613,7 @@
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Déverrouillage par reconnaissance faciale"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problème lié au déverrouillage par reconnaissance faciale"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"Appuyez pour supprimer votre empreinte faciale, puis ajoutez de nouveau votre visage"</string>
- <string name="face_setup_notification_title" msgid="8843461561970741790">"Configurer le déverrouillage facial"</string>
+ <string name="face_setup_notification_title" msgid="8843461561970741790">"Configurer le déverrouillage par reconnaissance faciale"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Déverrouillez votre téléphone en le regardant"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Configurer d\'autres méthodes de déverrouillage"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Appuyez pour ajouter une empreinte digitale"</string>
@@ -1071,7 +1071,7 @@
<string name="weeks" msgid="3516247214269821391">"semaines"</string>
<string name="year" msgid="5182610307741238982">"année"</string>
<string name="years" msgid="5797714729103773425">"années"</string>
- <string name="now_string_shortest" msgid="3684914126941650330">"mainten."</string>
+ <string name="now_string_shortest" msgid="3684914126941650330">"maintenant"</string>
<plurals name="duration_minutes_shortest" formatted="false" msgid="7519574894537185135">
<item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 12b80d4..f51a9a5 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1482,8 +1482,7 @@
<string name="deny" msgid="6632259981847676572">"નકારો"</string>
<string name="permission_request_notification_title" msgid="1810025922441048273">"પરવાનગીની વિનંતી કરી"</string>
<string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"એકાઉન્ટ <xliff:g id="ACCOUNT">%s</xliff:g> માટે\nપરવાનગીની વિનંતી કરી."</string>
- <!-- no translation found for permission_request_notification_for_app_with_subtitle (1298704005732851350) -->
- <skip />
+ <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"<xliff:g id="ACCOUNT">%2$s</xliff:g> એકાઉન્ટ માટે\n<xliff:g id="APP">%1$s</xliff:g> દ્વારા પરવાનગીની વિનંતી કરવામાં આવી."</string>
<string name="forward_intent_to_owner" msgid="4620359037192871015">"તમે તમારી કાર્ય પ્રોફાઇલની બહાર આ એપ્લિકેશનનો ઉપયોગ કરી રહ્યાં છો"</string>
<string name="forward_intent_to_work" msgid="3620262405636021151">"તમે તમારી કાર્ય પ્રોફાઇલમાં આ એપ્લિકેશનનો ઉપયોગ કરી રહ્યાં છો"</string>
<string name="input_method_binding_label" msgid="1166731601721983656">"ઇનપુટ પદ્ધતિ"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 667dd9c..5b390a3 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -617,7 +617,7 @@
<string name="face_setup_notification_content" msgid="5463999831057751676">"Taktu símann úr lás með því að horfa á hann"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Settu upp fleiri leiðir til að taka úr lás"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Ýttu til að bæta við fingrafari"</string>
- <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"Fingrafarskenni"</string>
+ <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"Fingrafarsopnun"</string>
<string name="fingerprint_recalibrate_notification_title" msgid="2406561052064558497">"Ekki er hægt að nota fingrafaralesara"</string>
<string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Þú verður að fara á verkstæði."</string>
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Nákvæm andlitsgögn fengust ekki. Reyndu aftur."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index d7730d7..6919a3d 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -2285,7 +2285,7 @@
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
<string name="window_magnification_prompt_title" msgid="2876703640772778215">"Nuove impostazioni per l\'ingrandimento"</string>
<string name="window_magnification_prompt_content" msgid="8159173903032344891">"Ora puoi ingrandire parte dello schermo"</string>
- <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Attiva nelle Impostazioni"</string>
+ <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Attiva in Impostazioni"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Ignora"</string>
<string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"Sblocca il microfono del dispositivo"</string>
<string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"Sblocca la fotocamera del dispositivo"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 5b5a90b..cd8cb90 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1522,8 +1522,7 @@
<string name="deny" msgid="6632259981847676572">"עדיף שלא"</string>
<string name="permission_request_notification_title" msgid="1810025922441048273">"בקשת הרשאה"</string>
<string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"נדרשת הרשאה\nלחשבון <xliff:g id="ACCOUNT">%s</xliff:g>."</string>
- <!-- no translation found for permission_request_notification_for_app_with_subtitle (1298704005732851350) -->
- <skip />
+ <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"התבקשה הרשאה על ידי <xliff:g id="APP">%1$s</xliff:g>\nלחשבון <xliff:g id="ACCOUNT">%2$s</xliff:g>."</string>
<string name="forward_intent_to_owner" msgid="4620359037192871015">"בחרת להשתמש באפליקציה הזאת מחוץ לפרופיל העבודה שלך"</string>
<string name="forward_intent_to_work" msgid="3620262405636021151">"נעשה שימוש באפליקציה הזו בפרופיל העבודה שלך"</string>
<string name="input_method_binding_label" msgid="1166731601721983656">"שיטת קלט"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 3243a8d35..6e82813 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -611,7 +611,7 @@
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Саусақ ізі белгішесі"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Бет тану"</string>
- <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Face Unlock функциясына қатысты мәселе шықты"</string>
+ <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Бет тану функциясына қатысты мәселе шықты"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"Бет үлгісін жою үшін түртіңіз, содан соң жаңа бет үлгісін қосыңыз."</string>
<string name="face_setup_notification_title" msgid="8843461561970741790">"Бет тану функциясын реттеу"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Телефоныңызға қарап, оның құлпын ашыңыз."</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index c610d25..a7d6ae0 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1482,8 +1482,7 @@
<string name="deny" msgid="6632259981847676572">"ನಿರಾಕರಿಸಿ"</string>
<string name="permission_request_notification_title" msgid="1810025922441048273">"ಅನುಮತಿ ವಿನಂತಿಸಲಾಗಿದೆ"</string>
<string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"<xliff:g id="ACCOUNT">%s</xliff:g> ಖಾತೆಗಾಗಿ\n ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸಲಾಗಿದೆ."</string>
- <!-- no translation found for permission_request_notification_for_app_with_subtitle (1298704005732851350) -->
- <skip />
+ <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"<xliff:g id="ACCOUNT">%2$s</xliff:g> ಖಾತೆಗಾಗಿ \n <xliff:g id="APP">%1$s</xliff:g> ನಿಂದ ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸಲಾಗಿದೆ."</string>
<string name="forward_intent_to_owner" msgid="4620359037192871015">"ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್ನ ಹೊರಗೆ ನೀವು ಈ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಬಳಸುತ್ತಿರುವಿರಿ"</string>
<string name="forward_intent_to_work" msgid="3620262405636021151">"ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್ನಲ್ಲಿ ನೀವು ಈ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಬಳಸುತ್ತಿರುವಿರಿ"</string>
<string name="input_method_binding_label" msgid="1166731601721983656">"ಇನ್ಪುಟ್ ವಿಧಾನ"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 8fddef0..174d732 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -648,7 +648,7 @@
<string name="face_error_canceled" msgid="2164434737103802131">"Жүздүн аныктыгын текшерүү жокко чыгарылды."</string>
<string name="face_error_user_canceled" msgid="5766472033202928373">"Жүзүнөн таанып ачуу функциясын колдонуучу өчүрүп салды"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Өтө көп жолу аракет жасадыңыз. Бир аздан кийин кайталап көрүңүз."</string>
- <string name="face_error_lockout_permanent" msgid="3277134834042995260">"Өтө көп жолу аракет кылдыңыз. Жүзүнөн таануу функциясы өчүрүлдү."</string>
+ <string name="face_error_lockout_permanent" msgid="3277134834042995260">"Өтө көп жолу аракет кылдыңыз. Жүзүнөн таанып ачуу функциясы өчүрүлдү."</string>
<string name="face_error_lockout_screen_lock" msgid="5062609811636860928">"Өтө көп жолу аракет кылдыңыз. Эрканды кулпулоо функциясын колдонуңуз."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Жүз ырасталбай жатат. Кайталап көрүңүз."</string>
<string name="face_error_not_enrolled" msgid="1134739108536328412">"Жүзүнөн таанып ачуу функциясын жөндөй элексиз"</string>
@@ -1482,7 +1482,7 @@
<string name="deny" msgid="6632259981847676572">"Уруксат берилбейт"</string>
<string name="permission_request_notification_title" msgid="1810025922441048273">"Уруксат талап кылуу"</string>
<string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"Кийинки эсепке\nуруксат талап кылынууда: <xliff:g id="ACCOUNT">%s</xliff:g>."</string>
- <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"<xliff:g id="APP">%1$s</xliff:g> колдонмосу\n <xliff:g id="ACCOUNT">%2$s</xliff:g> аккаунтуна кирүүгө уруксат сурады."</string>
+ <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"<xliff:g id="APP">%1$s</xliff:g> колдонмосу\n<xliff:g id="ACCOUNT">%2$s</xliff:g> аккаунтуна кирүүгө уруксат сурады."</string>
<string name="forward_intent_to_owner" msgid="4620359037192871015">"Бул колдонмо жумуш профилиңиздин сыртында колдонулуп жатат"</string>
<string name="forward_intent_to_work" msgid="3620262405636021151">"Бул колдонмону жумуш профилиңизде пайдаланып жатасыз"</string>
<string name="input_method_binding_label" msgid="1166731601721983656">"Киргизүү ыкмасы"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 31d0762..b29d49e 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -617,7 +617,7 @@
<string name="face_setup_notification_content" msgid="5463999831057751676">"Отклучете го телефонот со гледање во него"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Поставете уште начини за отклучување"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Допрете за да додадете отпечаток"</string>
- <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"Отклучување со отпечаток"</string>
+ <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"Отклучување со отпечаток на прст"</string>
<string name="fingerprint_recalibrate_notification_title" msgid="2406561052064558497">"Не може да се користи сензорот за отпечатоци"</string>
<string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Однесете го на поправка."</string>
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Не се сними прецизна слика. Обидете се повторно."</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index a4d9602..28522d7 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -652,7 +652,7 @@
<string name="face_error_lockout_screen_lock" msgid="5062609811636860928">"बरेच प्रयत्न. त्याऐवजी स्क्रीन लॉक वापरा."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"चेहरा पडताळणी करू शकत नाही. पुन्हा प्रयत्न करा."</string>
<string name="face_error_not_enrolled" msgid="1134739108536328412">"तुम्ही फेस अनलॉक सेट केले नाही"</string>
- <string name="face_error_hw_not_present" msgid="7940978724978763011">"फेस अनलॉक या डिव्हाइसवर सपोर्ट करत नाही"</string>
+ <string name="face_error_hw_not_present" msgid="7940978724978763011">"या डिव्हाइसवर फेस अनलॉकला सपोर्ट नाही"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"सेन्सर तात्पुरता बंद केला आहे."</string>
<string name="face_name_template" msgid="3877037340223318119">"चेहरा <xliff:g id="FACEID">%d</xliff:g>"</string>
<string name="face_app_setting_name" msgid="5854024256907828015">"फेस अनलॉक वापरा"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index b3631c6..36af211 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -914,13 +914,13 @@
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="3118353451602377380">"तपाईंले गलत तरिकाले आफ्नो पासवर्ड <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक टाइप गर्नुभयो। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
<string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="2874278239714821984">"तपाईँले गलत तरिकाले तपाईँको PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक टाइप गर्नु भएको छ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="3069635524964070596">"तपाईँले तपाईँको अनलक प्याटर्न गलत तरिकाले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक खिच्नु भएको छ। पछि <xliff:g id="NUMBER_1">%2$d</xliff:g> थप असफल कोसिसहरू, तपाईँको Google साइन इन प्रयोग गरी तपाईँको ट्याब्लेट अनलक गर्न भनिने छ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा फरि प्रयास गर्नुहोस्।"</string>
- <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"तपाईंले आफ्नो अनलक शैली <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले कोर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> प्रयासहरू असफल भएपछि तपाईंलाई आफ्नो Google खाता मार्फत साइन इन गरेर आफ्नो Android टिभी डिभाइस अनलक गर्न अनुरोध गरिनेछ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डपछि फेरि प्रयास गर्नुहोस्।"</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"तपाईंले आफ्नो अनलक शैली <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले कोर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> प्रयासहरू असफल भएपछि तपाईंलाई आफ्नो Google खाता मार्फत साइन इन गरेर आफ्नो Android टिभी डिभाइस अनलक गर्न अनुरोध गरिने छ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डपछि फेरि प्रयास गर्नुहोस्।"</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="5691623136957148335">"तपाईँले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले तपाईँको अनलक ढाँचालाई कोर्नु भएको छ। पछि <xliff:g id="NUMBER_1">%2$d</xliff:g> अरू धेरै असफल कोसिसहरूपछि, तपाईँलाई तपाईँको फोन Google साइन इन प्रयोग गरेर अनलक गर्नको लागि सोधिने छ। \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा पुनः प्रयास गर्नुहोस्।"</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="7914445759242151426">"तपाईँले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक ट्याब्लेटलाई अनलक गर्नको लागि गलत तरिकाले कोशिस गर्नुभएको छ। <xliff:g id="NUMBER_1">%2$d</xliff:g> अरू धेरै असफल कोसिसहरूपछि, ट्याब्लेट फ्याट्रि पूर्वनिर्धारितमा रिसेट हुने छ र सबै प्रयोगकर्ता डेटा हराउने छन्।"</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="4275591249631864248">"तपाईंले आफ्नो Android टिभी यन्त्र <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले अनलक गर्ने प्रयास गर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> प्रयासहरू असफल भएपछि तपाईंको Android टिभी यन्त्रलाई रिसेट गरेर डिफल्ट फ्याक्ट्री सेटिङ लागू गरिने छ र प्रयोगकर्ताको सम्पूर्ण डेटा गुम्ने छ।"</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="1166532464798446579">"तपाईंले गलत तरिकाले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक फोन अनलक गर्ने प्रयत्न गर्नुभयो। <xliff:g id="NUMBER_1">%2$d</xliff:g> बढी असफल प्रयत्नहरू पछि, फोन फ्याक्ट्रि पूर्वनिर्धारितमा रिसेट हुने छ र सबै प्रयोगकर्ता डेटा हराउने छन्।"</string>
<string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="8682445539263683414">"तपाईँले ट्यब्लेटलाई अनलक गर्न गलत तरिकाले <xliff:g id="NUMBER">%d</xliff:g> पटक प्रयास गर्नु भएको छ। अब ट्याब्लेटलाई डिफल्ट कार्यशालामा रिसेट गरिने छ।"</string>
- <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="2205435033340091883">"तपाईंले आफ्नो Android टिभी यन्त्र <xliff:g id="NUMBER">%d</xliff:g> पटक गलत तरिकाले अनलक गर्ने प्रयास गर्नुभएको छ। अब तपाईंको Android टिभी यन्त्रलाई रिसेट गरेर डिफल्ट फ्याक्ट्री सेटिङ लागू गरिनेछ।"</string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="2205435033340091883">"तपाईंले आफ्नो Android टिभी यन्त्र <xliff:g id="NUMBER">%d</xliff:g> पटक गलत तरिकाले अनलक गर्ने प्रयास गर्नुभएको छ। अब तपाईंको Android टिभी यन्त्रलाई रिसेट गरेर डिफल्ट फ्याक्ट्री सेटिङ लागू गरिने छ।"</string>
<string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="2203704707679895487">"तपाईंले गलत तरिकाले फोन <xliff:g id="NUMBER">%d</xliff:g> पटक अनलक गर्ने प्रयत्न गर्नुभयो। अब फोन फ्याक्ट्रि पूर्वनिर्धारितमा रिसेट हुने छ।"</string>
<string name="lockscreen_too_many_failed_attempts_countdown" msgid="6807200118164539589">"<xliff:g id="NUMBER">%d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
<string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"ढाँचा बिर्सनु भयो?"</string>
@@ -1679,10 +1679,10 @@
<string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="9064457748587850217">"तपाईंले आफ्नो Android टिभी यन्त्र <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले अनलक गर्ने प्रयास गर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> प्रयासहरू असफल भएपछि तपाईंको Android टिभी यन्त्रलाई रिसेट गरेर डिफल्ट फ्याक्ट्री सेटिङ लागू गरिने छ र प्रयोगकर्ताको सम्पूर्ण डेटा गुम्ने छ।"</string>
<string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="5955398963754432548">"तपाईँले गलतसँग फोनलाई अनलक गर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक कोसिस गर्नु भयो। <xliff:g id="NUMBER_1">%2$d</xliff:g> पछि थप असफल कोसिसहरू, फोनलाई डिफल्ट कार्यशालामा रिसेट गरिने छ र सबै प्रयोग डेटा हराउने छ।"</string>
<string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2299099385175083308">"तपाईँले ट्यब्लेटलाई अनलक गर्न गलत तरिकाले <xliff:g id="NUMBER">%d</xliff:g> पटक प्रयास गर्नु भएको छ। अब ट्याब्लेटलाई डिफल्ट कार्यशालामा रिसेट गरिने छ।"</string>
- <string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"तपाईंले आफ्नो Android टिभी यन्त्र <xliff:g id="NUMBER">%d</xliff:g> पटक गलत तरिकाले अनलक गर्ने प्रयास गर्नुभएको छ। अब तपाईंको Android टिभी यन्त्रलाई रिसेट गरेर डिफल्ट फ्याक्ट्री सेटिङ लागू गरिनेछ।"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"तपाईंले आफ्नो Android टिभी यन्त्र <xliff:g id="NUMBER">%d</xliff:g> पटक गलत तरिकाले अनलक गर्ने प्रयास गर्नुभएको छ। अब तपाईंको Android टिभी यन्त्रलाई रिसेट गरेर डिफल्ट फ्याक्ट्री सेटिङ लागू गरिने छ।"</string>
<string name="kg_failed_attempts_now_wiping" product="default" msgid="5043730590446071189">"तपाईंले गलत तरिकाले फोन <xliff:g id="NUMBER">%d</xliff:g> पटक अनलक गर्ने प्रयत्न गर्नुभयो। अब फोन फ्याक्ट्रि पूर्वनिर्धारितमा रिसेट हुने छ।"</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"तपाईंले गलत तरिकाले आफ्नो अनलक प्याटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक कोर्नुभयो। <xliff:g id="NUMBER_1">%2$d</xliff:g> विफल प्रयत्नहरू पछि, तपाईंलाई आफ्नो ट्याब्लेट इमेल खाता प्रयोग गरेर अनलक गर्न सोधिने छ।\n\n फेरि प्रयास गर्नुहोस् <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डहरूमा।"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"तपाईंले आफ्नो अनलक शैली <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले कोर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> प्रयासहरू असफल भएपछि तपाईंलाई आफ्नो इमेल खाता प्रयोग गरेर आफ्नो Android टिभी डिभाइस अनलक गर्न अनुरोध गरिनेछ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डपछि फेरि प्रयास गर्नुहोस्।"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"तपाईंले आफ्नो अनलक शैली <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले कोर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> प्रयासहरू असफल भएपछि तपाईंलाई आफ्नो इमेल खाता प्रयोग गरेर आफ्नो Android टिभी डिभाइस अनलक गर्न अनुरोध गरिने छ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डपछि फेरि प्रयास गर्नुहोस्।"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"तपाईँले आफ्नो अनलक प्याटर्न गलत रूपमा <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक तान्नु भएको छ। <xliff:g id="NUMBER_1">%2$d</xliff:g> धेरै असफल प्रयासहरूपछि, तपाईँलाई एउटा इमेल खाताको प्रयोग गरेर तपाईँको फोन अनलक गर्न सोधिने छ।\n\n फेरि <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा प्रयास गर्नुहोस्।"</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"हटाउनुहोस्"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 26c5a3b..75857ff 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -610,10 +610,10 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Vingerafdruk-icoon"</string>
- <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ontgrendelen via gezicht"</string>
+ <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ontgrendelen via gezichtsherkenning"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Probleem met Ontgrendelen via gezichtsherkenning"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"Tik om je gezichtsmodel te verwijderen en voeg je gezicht opnieuw toe"</string>
- <string name="face_setup_notification_title" msgid="8843461561970741790">"Ontgrendeling via gezichtsherkenning instellen"</string>
+ <string name="face_setup_notification_title" msgid="8843461561970741790">"Ontgrendelen via gezichtsherkenning instellen"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Ontgrendel je telefoon door ernaar te kijken"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Stel meer manieren in om te ontgrendelen"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Tik om een vingerafdruk toe te voegen"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 027101d..209c6a1 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1482,8 +1482,7 @@
<string name="deny" msgid="6632259981847676572">"ਅਸਵੀਕਾਰ ਕਰੋ"</string>
<string name="permission_request_notification_title" msgid="1810025922441048273">"ਅਨੁਮਤੀ ਦੀ ਬੇਨਤੀ ਕੀਤੀ"</string>
<string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"<xliff:g id="ACCOUNT">%s</xliff:g> ਖਾਤੇ ਲਈ ਅਨੁਮਤੀ ਦੀ ਬੇਨਤੀ ਕੀਤੀ\n।"</string>
- <!-- no translation found for permission_request_notification_for_app_with_subtitle (1298704005732851350) -->
- <skip />
+ <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"<xliff:g id="APP">%1$s</xliff:g> ਨੇ <xliff:g id="ACCOUNT">%2$s</xliff:g> ਖਾਤੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ\nਦੀ ਇਜਾਜ਼ਤ ਲਈ ਬੇਨਤੀ ਕੀਤੀ।"</string>
<string name="forward_intent_to_owner" msgid="4620359037192871015">"ਤੁਸੀਂ ਇਹ ਐਪ ਆਪਣੀ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਦੇ ਬਾਹਰ ਵਰਤ ਰਹੇ ਹੋ"</string>
<string name="forward_intent_to_work" msgid="3620262405636021151">"ਤੁਸੀਂ ਇਹ ਐਪ ਆਪਣੀ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਵਰਤ ਰਹੇ ਹੋ"</string>
<string name="input_method_binding_label" msgid="1166731601721983656">"ਇਨਪੁੱਟ ਵਿਧੀ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index a9423619..c45ac41 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -250,7 +250,7 @@
<string name="global_action_power_off" msgid="4404936470711393203">"Wyłącz"</string>
<string name="global_action_power_options" msgid="1185286119330160073">"Przycisk zasilania"</string>
<string name="global_action_restart" msgid="4678451019561687074">"Uruchom ponownie"</string>
- <string name="global_action_emergency" msgid="1387617624177105088">"Nagły przypadek"</string>
+ <string name="global_action_emergency" msgid="1387617624177105088">"Połączenie alarmowe"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"Zgłoś błąd"</string>
<string name="global_action_logout" msgid="6093581310002476511">"Zakończ sesję"</string>
<string name="global_action_screenshot" msgid="2610053466156478564">"Zrzut ekranu"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 0578734..8198ae9 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -611,9 +611,9 @@
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ícone de impressão digital"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueio facial"</string>
- <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema com o desbloqueio facial"</string>
+ <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema com o Desbloqueio facial"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"Toque para excluir seu modelo de rosto e crie um novo"</string>
- <string name="face_setup_notification_title" msgid="8843461561970741790">"Configurar o desbloqueio facial"</string>
+ <string name="face_setup_notification_title" msgid="8843461561970741790">"Configurar o Desbloqueio facial"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Desbloqueie o smartphone olhando para ele"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Configure mais formas de desbloquear a tela"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Toque para adicionar uma impressão digital"</string>
@@ -643,7 +643,7 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Impossível verificar rosto. Hardware indisponível."</string>
- <string name="face_error_timeout" msgid="2598544068593889762">"Tente usar o desbloqueio facial novamente"</string>
+ <string name="face_error_timeout" msgid="2598544068593889762">"Tente usar o Desbloqueio facial novamente"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Não é possível salvar dados faciais. Exclua dados antigos."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Operação facial cancelada."</string>
<string name="face_error_user_canceled" msgid="5766472033202928373">"Desbloqueio facial cancelado pelo usuário"</string>
@@ -651,11 +651,11 @@
<string name="face_error_lockout_permanent" msgid="3277134834042995260">"Muitas tentativas. Desbloqueio facial desativado."</string>
<string name="face_error_lockout_screen_lock" msgid="5062609811636860928">"Muitas tentativas. Como alternativa, use o bloqueio de tela."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Não é possível verificar o rosto. Tente novamente."</string>
- <string name="face_error_not_enrolled" msgid="1134739108536328412">"O desbloqueio facial não foi configurado"</string>
- <string name="face_error_hw_not_present" msgid="7940978724978763011">"O dispositivo não é compatível com o desbloqueio facial"</string>
+ <string name="face_error_not_enrolled" msgid="1134739108536328412">"O Desbloqueio facial não foi configurado"</string>
+ <string name="face_error_hw_not_present" msgid="7940978724978763011">"O dispositivo não é compatível com o Desbloqueio facial"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Sensor desativado temporariamente."</string>
<string name="face_name_template" msgid="3877037340223318119">"Rosto <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="5854024256907828015">"Usar o desbloqueio facial"</string>
+ <string name="face_app_setting_name" msgid="5854024256907828015">"Usar o Desbloqueio facial"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Usar reconhecimento facial ou bloqueio de tela"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Use seu rosto para continuar"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use seu rosto ou o bloqueio de tela para continuar"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 0578734..8198ae9 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -611,9 +611,9 @@
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ícone de impressão digital"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueio facial"</string>
- <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema com o desbloqueio facial"</string>
+ <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema com o Desbloqueio facial"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"Toque para excluir seu modelo de rosto e crie um novo"</string>
- <string name="face_setup_notification_title" msgid="8843461561970741790">"Configurar o desbloqueio facial"</string>
+ <string name="face_setup_notification_title" msgid="8843461561970741790">"Configurar o Desbloqueio facial"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Desbloqueie o smartphone olhando para ele"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Configure mais formas de desbloquear a tela"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Toque para adicionar uma impressão digital"</string>
@@ -643,7 +643,7 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Impossível verificar rosto. Hardware indisponível."</string>
- <string name="face_error_timeout" msgid="2598544068593889762">"Tente usar o desbloqueio facial novamente"</string>
+ <string name="face_error_timeout" msgid="2598544068593889762">"Tente usar o Desbloqueio facial novamente"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Não é possível salvar dados faciais. Exclua dados antigos."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Operação facial cancelada."</string>
<string name="face_error_user_canceled" msgid="5766472033202928373">"Desbloqueio facial cancelado pelo usuário"</string>
@@ -651,11 +651,11 @@
<string name="face_error_lockout_permanent" msgid="3277134834042995260">"Muitas tentativas. Desbloqueio facial desativado."</string>
<string name="face_error_lockout_screen_lock" msgid="5062609811636860928">"Muitas tentativas. Como alternativa, use o bloqueio de tela."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Não é possível verificar o rosto. Tente novamente."</string>
- <string name="face_error_not_enrolled" msgid="1134739108536328412">"O desbloqueio facial não foi configurado"</string>
- <string name="face_error_hw_not_present" msgid="7940978724978763011">"O dispositivo não é compatível com o desbloqueio facial"</string>
+ <string name="face_error_not_enrolled" msgid="1134739108536328412">"O Desbloqueio facial não foi configurado"</string>
+ <string name="face_error_hw_not_present" msgid="7940978724978763011">"O dispositivo não é compatível com o Desbloqueio facial"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Sensor desativado temporariamente."</string>
<string name="face_name_template" msgid="3877037340223318119">"Rosto <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="5854024256907828015">"Usar o desbloqueio facial"</string>
+ <string name="face_app_setting_name" msgid="5854024256907828015">"Usar o Desbloqueio facial"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Usar reconhecimento facial ou bloqueio de tela"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Use seu rosto para continuar"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use seu rosto ou o bloqueio de tela para continuar"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 89494f2..132ee6f 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -610,14 +610,14 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ඇඟිලි සලකුණු නිරූපකය"</string>
- <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"මුහුණෙන් අගුළු ඇරීම"</string>
+ <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"මුහුණෙන් අගුළු හැරීම"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"මුහුණෙන් අගුලු හැරීම සම්බන්ධව ගැටලුවකි"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"ඔබගේ මුහුණත ආකෘතිය මැකීමට තට්ටු කරන්න, අනතුරුව ඔබගේ මුහුණ නැවත එක් කරන්න"</string>
- <string name="face_setup_notification_title" msgid="8843461561970741790">"මුහුණෙන් අගුළු ඇරීම පිහිටුවන්න"</string>
+ <string name="face_setup_notification_title" msgid="8843461561970741790">"මුහුණෙන් අගුළු හැරීම පිහිටුවන්න"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"ඔබගේ දුරකථනය දෙස බැලීමෙන් එහි අගුලු හරින්න"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"අගුලු හැරීමට තවත් ක්රම සකසන්න"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"ඇඟිලි සලකුණක් එක් කිරීමට තට්ටු කරන්න"</string>
- <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"ඇඟිලි සලකුණු අගුළු ඇරීම"</string>
+ <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"ඇඟිලි සලකුණු අගුළු හැරීම"</string>
<string name="fingerprint_recalibrate_notification_title" msgid="2406561052064558497">"ඇඟිලි සලකුණු සංවේදකය භාවිත කළ නොහැකිය"</string>
<string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"අළුත්වැඩියා සැපයුම්කරුවෙකු බලන්න."</string>
<string name="face_acquired_insufficient" msgid="2150805835949162453">"නිරවද්ය මුහුණු දත්ත ගත නොහැකි විය. නැවත උත්සාහ කරන්න."</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"මුහුණ සත්යාපනය කළ නොහැක. දෘඩාංගය නොමැත."</string>
- <string name="face_error_timeout" msgid="2598544068593889762">"මුහුණෙන් අගුළු ඇරීම නැවත උත්සාහ කරන්න."</string>
+ <string name="face_error_timeout" msgid="2598544068593889762">"මුහුණෙන් අගුළු හැරීම නැවත උත්සාහ කරන්න."</string>
<string name="face_error_no_space" msgid="5649264057026021723">"නව මුහුණු දත්ත ගබඩා කළ නොහැක. පළමුව පැරණි එකක් මකන්න."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"මුහුණු මෙහෙයුම අවලංගු කරන ලදී."</string>
- <string name="face_error_user_canceled" msgid="5766472033202928373">"පරිශීලකයා විසින් මුහුණෙන් අගුළු ඇරීම අවලංගු කරන ලදි"</string>
+ <string name="face_error_user_canceled" msgid="5766472033202928373">"පරිශීලකයා විසින් මුහුණෙන් අගුළු හැරීම අවලංගු කරන ලදි"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"උත්සාහයන් ඉතා වැඩි ගණනකි. පසුව නැවත උත්සාහ කරන්න."</string>
- <string name="face_error_lockout_permanent" msgid="3277134834042995260">"උත්සාහයන් ඉතා වැඩි ගණනකි. මුහුණෙන් අගුළු ඇරීම අබලයි."</string>
+ <string name="face_error_lockout_permanent" msgid="3277134834042995260">"උත්සාහයන් ඉතා වැඩි ගණනකි. මුහුණෙන් අගුළු හැරීම අබලයි."</string>
<string name="face_error_lockout_screen_lock" msgid="5062609811636860928">"උත්සාහයන් ඉතා වැඩි ගණනකි. ඒ වෙනුවට තිර අගුල ඇතුළු කරන්න."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"මුහුණ සත්යාපන කළ නොහැක. නැවත උත්සාහ කරන්න."</string>
- <string name="face_error_not_enrolled" msgid="1134739108536328412">"ඔබ මුහුණෙන් අගුළු ඇරීම පිහිටුවා නැත"</string>
- <string name="face_error_hw_not_present" msgid="7940978724978763011">"මුහුණෙන් අගුළු ඇරීම මෙම උපාංගයේ සහාය නොදක්වයි."</string>
+ <string name="face_error_not_enrolled" msgid="1134739108536328412">"ඔබ මුහුණෙන් අගුළු හැරීම පිහිටුවා නැත"</string>
+ <string name="face_error_hw_not_present" msgid="7940978724978763011">"මුහුණෙන් අගුළු හැරීම මෙම උපාංගයේ සහාය නොදක්වයි."</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"සංවේදකය තාවකාලිකව අබල කර ඇත."</string>
<string name="face_name_template" msgid="3877037340223318119">"මුහුණු <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="5854024256907828015">"මුහුණෙන් අගුළු ඇරීම භාවිත කර."</string>
+ <string name="face_app_setting_name" msgid="5854024256907828015">"මුහුණෙන් අගුළු හැරීම භාවිත කර."</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"මුහුණෙන් අගුළු හැරීම හෝ තිර අගුල භාවිත කරන්න"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"ඉදිරියට යාමට ඔබගේ මුහුණ භාවිත කරන්න"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ඉදිරියට යාමට ඔබගේ මුහුණු හෝ තිර අගුල භාවිත කරන්න"</string>
@@ -958,7 +958,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"අගුළු නොදැමූ ප්රදේශය පුළුල් කරන්න."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"සර්පණ අගුළු ඇරීම."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"රටා අගුළු ඇරීම."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"මුහුණෙන් අගුළු ඇරීම."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"මුහුණෙන් අගුළු හැරීම."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"PIN අගුළු ඇරීම."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Sim Pin අගුලු දැමීම."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Sim Puk අගුලු දැමීම."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 3d731e7..afdf1d9 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -26,7 +26,7 @@
<string name="gigabyteShort" msgid="7515809460261287991">"GB"</string>
<string name="terabyteShort" msgid="1822367128583886496">"TB"</string>
<string name="petabyteShort" msgid="5651571254228534832">"PB"</string>
- <string name="fileSizeSuffix" msgid="4233671691980131257">"<xliff:g id="NUMBER">%1$s</xliff:g>&#160;<xliff:g id="UNIT">%2$s</xliff:g>"</string>
+ <string name="fileSizeSuffix" msgid="4233671691980131257">"<xliff:g id="NUMBER">%1$s</xliff:g>U+00A0<xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="3381766946944136678">"<Bez mena>"</string>
<string name="emptyPhoneNumber" msgid="5812172618020360048">"(žiadne telefónne číslo)"</string>
<string name="unknownName" msgid="7078697621109055330">"Bez názvu"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 52f01e2..25e2820 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -958,7 +958,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Zgjero zonën e shkyçjes."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Rrëshqit shkyçjen."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Shkyçje me motiv."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"Shkyçja me fytyrë"</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"Shkyçja me fytyrë."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Shkyçje me PIN."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Shkyçja e kartës SIM me kodin PIN"</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Shkyçja e kartës SIM me kodin PUK"</string>
@@ -1482,8 +1482,7 @@
<string name="deny" msgid="6632259981847676572">"Moho"</string>
<string name="permission_request_notification_title" msgid="1810025922441048273">"Kërkohet leje"</string>
<string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"Kërkohet leje\npër llogarinë <xliff:g id="ACCOUNT">%s</xliff:g>."</string>
- <!-- no translation found for permission_request_notification_for_app_with_subtitle (1298704005732851350) -->
- <skip />
+ <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"Kërkohet leja nga <xliff:g id="APP">%1$s</xliff:g>\npër llogarinë <xliff:g id="ACCOUNT">%2$s</xliff:g>."</string>
<string name="forward_intent_to_owner" msgid="4620359037192871015">"Po e përdor këtë aplikacion jashtë profilit tënd të punës"</string>
<string name="forward_intent_to_work" msgid="3620262405636021151">"Këtë aplikacion po e përdor në profilin tënd të punës"</string>
<string name="input_method_binding_label" msgid="1166731601721983656">"Metoda e hyrjeve"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 29e4a71..fbee2c3 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -610,10 +610,10 @@
<string-array name="fingerprint_error_vendor">
</string-array>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Aikoni ya alama ya kidole"</string>
- <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Kufungua kwa uso"</string>
- <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Hitilafu imetokea kwenye kipengele cha Kufungua kwa uso"</string>
+ <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Kufungua kwa Uso"</string>
+ <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Hitilafu imetokea kwenye kipengele cha Kufungua kwa Uso"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"Gusa ili ufute muundo wa uso wako, kisha uweke uso wako tena"</string>
- <string name="face_setup_notification_title" msgid="8843461561970741790">"Weka mipangilio ya Kufungua kwa uso"</string>
+ <string name="face_setup_notification_title" msgid="8843461561970741790">"Weka mipangilio ya Kufungua kwa Uso"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Fungua simu yako kwa kuiangalia"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Weka mipangilio ya mbinu zaidi za kufungua"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Gusa ili uweke alama ya kidole"</string>
@@ -643,19 +643,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Imeshindwa kuthibitisha uso. Maunzi hayapatikani."</string>
- <string name="face_error_timeout" msgid="2598544068593889762">"Jaribu Kufungua kwa uso tena"</string>
+ <string name="face_error_timeout" msgid="2598544068593889762">"Jaribu Kufungua kwa Uso tena"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Imeshindwa kuhifadhi data ya uso mpya. Futa wa kale kwanza."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Utendaji wa kitambulisho umeghairiwa."</string>
- <string name="face_error_user_canceled" msgid="5766472033202928373">"Hatua ya Kufungua kwa uso imeghairiwa na mtumiaji"</string>
+ <string name="face_error_user_canceled" msgid="5766472033202928373">"Hatua ya Kufungua kwa Uso imeghairiwa na mtumiaji"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Umejaribu mara nyingi mno. Jaribu tena baadaye."</string>
- <string name="face_error_lockout_permanent" msgid="3277134834042995260">"Umejaribu mara nyingi mno. Umezima kipengele cha Kufungua kwa uso."</string>
+ <string name="face_error_lockout_permanent" msgid="3277134834042995260">"Umejaribu mara nyingi mno. Umezima kipengele cha Kufungua kwa Uso."</string>
<string name="face_error_lockout_screen_lock" msgid="5062609811636860928">"Umejaribu mara nyingi mno. Weka mbinu ya kufunga skrini badala yake."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Imeshindwa kuthibitisha uso. Jaribu tena."</string>
- <string name="face_error_not_enrolled" msgid="1134739108536328412">"Hujaweka mipangilio ya kipengele cha Kufungua kwa uso"</string>
- <string name="face_error_hw_not_present" msgid="7940978724978763011">"Kipengele cha Kufungua kwa uso hakitumiki kwenye kifaa hiki"</string>
+ <string name="face_error_not_enrolled" msgid="1134739108536328412">"Hujaweka mipangilio ya kipengele cha Kufungua kwa Uso"</string>
+ <string name="face_error_hw_not_present" msgid="7940978724978763011">"Kipengele cha Kufungua kwa Uso hakitumiki kwenye kifaa hiki"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Kitambuzi kimezimwa kwa muda."</string>
<string name="face_name_template" msgid="3877037340223318119">"Uso wa <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="5854024256907828015">"Tumia kipengele cha Kufungua kwa uso"</string>
+ <string name="face_app_setting_name" msgid="5854024256907828015">"Tumia kipengele cha Kufungua kwa Uso"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Tumia uso au mbinu ya kufunga skrini"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Tumia uso wako ili uendelee"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Tumia uso au mbinu yako ya kufunga skrini ili uendelee"</string>
@@ -958,7 +958,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Panua eneo la kufungua."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Kufungua slaidi."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Kufungua kwa ruwaza."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"Kufungua kwa uso."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"Kufungua kwa Uso."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Kufungua kwa PIN."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Kufungua Pin ya Sim."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Kufungua Puk ya Sim."</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index fcce9b4..18b588c 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1990,7 +1990,7 @@
<string name="profile_encrypted_detail" msgid="5279730442756849055">"பணிக் கணக்கு பூட்டியுள்ளது"</string>
<string name="profile_encrypted_message" msgid="1128512616293157802">"பணிக் கணக்கை அன்லாக் செய்யத் தட்டுக"</string>
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> உடன் இணைக்கப்பட்டது"</string>
- <string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"கோப்புகளைப் பார்க்க, தட்டவும்"</string>
+ <string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"ஃபைல்களைப் பார்க்க, தட்டவும்"</string>
<string name="pin_target" msgid="8036028973110156895">"பின் செய்"</string>
<string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> ஐப் பின் செய்"</string>
<string name="unpin_target" msgid="3963318576590204447">"பின்னை அகற்று"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index c57210e..1b4598a 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1522,7 +1522,7 @@
<string name="deny" msgid="6632259981847676572">"Забор."</string>
<string name="permission_request_notification_title" msgid="1810025922441048273">"Потрібен дозвіл"</string>
<string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"Запитано дозвіл\nдля облікового запису <xliff:g id="ACCOUNT">%s</xliff:g>."</string>
- <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"Дозвіл, який додаток <xliff:g id="APP">%1$s</xliff:g> запитує\nна доступ до облікового запису <xliff:g id="ACCOUNT">%2$s</xliff:g>."</string>
+ <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"Додаток <xliff:g id="APP">%1$s</xliff:g> запитує дозвіл\nна доступ до облікового запису <xliff:g id="ACCOUNT">%2$s</xliff:g>."</string>
<string name="forward_intent_to_owner" msgid="4620359037192871015">"Ви використовуєте цей додаток за межами робочого профілю"</string>
<string name="forward_intent_to_work" msgid="3620262405636021151">"Ви використовуєте цей додаток у своєму робочому профілі"</string>
<string name="input_method_binding_label" msgid="1166731601721983656">"Метод введення"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8dfbdcc..2770cbe 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3370,8 +3370,7 @@
<integer name="config_vibrationWaveformRampStepDuration">5</integer>
<!-- The duration (in milliseconds) that should be applied to waveform vibrations that ends in
- non-zero amplitudes, . The waveform will
- be played as a PWLE instead of on/off calls if this value is set. -->
+ non-zero amplitudes, to bring the vibrator amplitude down to zero using this timing. -->
<integer name="config_vibrationWaveformRampDownDuration">0</integer>
<!-- Number of retries Cell Data should attempt for a given error code before
diff --git a/core/tests/coretests/src/android/content/pm/ConstrainDisplayApisConfigTest.java b/core/tests/coretests/src/android/content/pm/ConstrainDisplayApisConfigTest.java
index 1dfbfcd..0456029 100644
--- a/core/tests/coretests/src/android/content/pm/ConstrainDisplayApisConfigTest.java
+++ b/core/tests/coretests/src/android/content/pm/ConstrainDisplayApisConfigTest.java
@@ -48,7 +48,8 @@
public void setUp() throws Exception {
mInitialConstrainDisplayApisFlags = DeviceConfig.getProperties(
NAMESPACE_CONSTRAIN_DISPLAY_APIS);
- clearConstrainDisplayApisFlags();
+ DeviceConfig.setProperties(
+ new Properties.Builder(NAMESPACE_CONSTRAIN_DISPLAY_APIS).build());
}
@After
@@ -120,6 +121,29 @@
testNeverConstrainDisplayApis("com.android.test5", /* version= */ 5, /* expected= */ true);
}
+ @Test
+ public void alwaysConstrainDisplayApis_flagsNoSet_returnsFalse() {
+ testAlwaysConstrainDisplayApis("com.android.test", /* version= */ 1, /* expected= */ false);
+ }
+
+ @Test
+ public void alwaysConstrainDisplayApis_flagHasEntries_returnsTrueForPackagesWithinRange() {
+ setAlwaysConstrainDisplayApisFlag("com.android.test1::,com.android.test2:1:2");
+
+ // Package 'com.android.other'
+ testAlwaysConstrainDisplayApis("com.android.other", /* version= */ 5, /* expected= */
+ false);
+ // Package 'com.android.test1'
+ testAlwaysConstrainDisplayApis("com.android.test1", /* version= */ 5, /* expected= */ true);
+ // Package 'com.android.test2'
+ testAlwaysConstrainDisplayApis("com.android.test2", /* version= */ 0, /* expected= */
+ false);
+ testAlwaysConstrainDisplayApis("com.android.test2", /* version= */ 1, /* expected= */ true);
+ testAlwaysConstrainDisplayApis("com.android.test2", /* version= */ 2, /* expected= */ true);
+ testAlwaysConstrainDisplayApis("com.android.test2", /* version= */ 3, /* expected= */
+ false);
+ }
+
private static void testNeverConstrainDisplayApis(String packageName, long version,
boolean expected) {
boolean result = ConstrainDisplayApisConfig.neverConstrainDisplayApis(
@@ -131,6 +155,17 @@
}
}
+ private static void testAlwaysConstrainDisplayApis(String packageName, long version,
+ boolean expected) {
+ boolean result = ConstrainDisplayApisConfig.alwaysConstrainDisplayApis(
+ buildApplicationInfo(packageName, version));
+ if (expected) {
+ assertTrue(result);
+ } else {
+ assertFalse(result);
+ }
+ }
+
private static ApplicationInfo buildApplicationInfo(String packageName, long version) {
ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.packageName = packageName;
@@ -149,8 +184,8 @@
value, /* makeDefault= */ false);
}
- private static void clearConstrainDisplayApisFlags() {
- setNeverConstrainDisplayApisFlag(null);
- setNeverConstrainDisplayApisAllPackagesFlag(null);
+ private static void setAlwaysConstrainDisplayApisFlag(@Nullable String value) {
+ DeviceConfig.setProperty(NAMESPACE_CONSTRAIN_DISPLAY_APIS, "always_constrain_display_apis",
+ value, /* makeDefault= */ false);
}
}
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index ac5e2d0..b67988e 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -151,6 +151,12 @@
"group": "WM_DEBUG_ADD_REMOVE",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-1963363332": {
+ "message": "Restart top activity process of Task taskId=%d",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_WINDOW_ORGANIZER",
+ "at": "com\/android\/server\/wm\/TaskOrganizerController.java"
+ },
"-1949279037": {
"message": "Attempted to add input method window with bad token %s. Aborting.",
"level": "WARN",
@@ -163,12 +169,6 @@
"group": "WM_DEBUG_WINDOW_ORGANIZER",
"at": "com\/android\/server\/wm\/TaskOrganizerController.java"
},
- "-1939358269": {
- "message": "mRecentScreenshotAnimator finish",
- "level": "DEBUG",
- "group": "WM_DEBUG_RECENTS_ANIMATIONS",
- "at": "com\/android\/server\/wm\/RecentsAnimationController.java"
- },
"-1938839202": {
"message": "SURFACE LEAK DESTROY: %s",
"level": "INFO",
@@ -3499,12 +3499,6 @@
"group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/AppTransitionController.java"
},
- "1984470582": {
- "message": "Creating TaskScreenshotAnimatable: task: %s width: %d height: %d",
- "level": "DEBUG",
- "group": "WM_DEBUG_RECENTS_ANIMATIONS",
- "at": "com\/android\/server\/wm\/TaskScreenshotAnimatable.java"
- },
"1984782949": {
"message": ">>> OPEN TRANSACTION animate",
"level": "INFO",
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index dc7f3dd..7258a3a 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.app.ActivityThread;
import android.content.Context;
+import android.hardware.security.keymint.EcCurve;
import android.hardware.security.keymint.KeyParameter;
import android.hardware.security.keymint.KeyPurpose;
import android.hardware.security.keymint.SecurityLevel;
@@ -122,6 +123,7 @@
new HashMap<String, Integer>();
private static final List<String> SUPPORTED_EC_NIST_CURVE_NAMES = new ArrayList<String>();
private static final List<Integer> SUPPORTED_EC_NIST_CURVE_SIZES = new ArrayList<Integer>();
+
static {
// Aliases for NIST P-224
SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-224", 224);
@@ -175,12 +177,29 @@
mOriginalKeymasterAlgorithm = keymasterAlgorithm;
}
+ private @EcCurve int keySize2EcCurve(int keySizeBits)
+ throws InvalidAlgorithmParameterException {
+ switch (keySizeBits) {
+ case 224:
+ return EcCurve.P_224;
+ case 256:
+ return EcCurve.P_256;
+ case 384:
+ return EcCurve.P_384;
+ case 521:
+ return EcCurve.P_521;
+ default:
+ throw new InvalidAlgorithmParameterException(
+ "Unsupported EC curve keysize: " + keySizeBits);
+ }
+ }
+
@SuppressWarnings("deprecation")
@Override
public void initialize(int keysize, SecureRandom random) {
throw new IllegalArgumentException(
KeyGenParameterSpec.class.getName() + " or " + KeyPairGeneratorSpec.class.getName()
- + " required to initialize this KeyPairGenerator");
+ + " required to initialize this KeyPairGenerator");
}
@SuppressWarnings("deprecation")
@@ -194,7 +213,7 @@
if (params == null) {
throw new InvalidAlgorithmParameterException(
"Must supply params of type " + KeyGenParameterSpec.class.getName()
- + " or " + KeyPairGeneratorSpec.class.getName());
+ + " or " + KeyPairGeneratorSpec.class.getName());
}
KeyGenParameterSpec spec;
@@ -215,8 +234,8 @@
} else {
throw new InvalidAlgorithmParameterException(
"Unsupported params class: " + params.getClass().getName()
- + ". Supported: " + KeyGenParameterSpec.class.getName()
- + ", " + KeyPairGeneratorSpec.class.getName());
+ + ". Supported: " + KeyGenParameterSpec.class.getName()
+ + ", " + KeyPairGeneratorSpec.class.getName());
}
mEntryAlias = spec.getKeystoreAlias();
@@ -250,11 +269,11 @@
keymasterPadding)) {
throw new InvalidAlgorithmParameterException(
"Randomized encryption (IND-CPA) required but may be violated"
- + " by padding scheme: "
- + KeyProperties.EncryptionPadding.fromKeymaster(
+ + " by padding scheme: "
+ + KeyProperties.EncryptionPadding.fromKeymaster(
keymasterPadding)
- + ". See " + KeyGenParameterSpec.class.getName()
- + " documentation.");
+ + ". See " + KeyGenParameterSpec.class.getName()
+ + " documentation.");
}
}
}
@@ -378,7 +397,7 @@
specBuilder = new KeyGenParameterSpec.Builder(
legacySpec.getKeystoreAlias(),
KeyProperties.PURPOSE_SIGN
- | KeyProperties.PURPOSE_VERIFY);
+ | KeyProperties.PURPOSE_VERIFY);
// Authorized to be used with any digest (including no digest).
// MD5 was never offered for Android Keystore for ECDSA.
specBuilder.setDigests(
@@ -393,9 +412,9 @@
specBuilder = new KeyGenParameterSpec.Builder(
legacySpec.getKeystoreAlias(),
KeyProperties.PURPOSE_ENCRYPT
- | KeyProperties.PURPOSE_DECRYPT
- | KeyProperties.PURPOSE_SIGN
- | KeyProperties.PURPOSE_VERIFY);
+ | KeyProperties.PURPOSE_DECRYPT
+ | KeyProperties.PURPOSE_SIGN
+ | KeyProperties.PURPOSE_VERIFY);
// Authorized to be used with any digest (including no digest).
specBuilder.setDigests(
KeyProperties.DIGEST_NONE,
@@ -459,8 +478,7 @@
private void initAlgorithmSpecificParameters() throws InvalidAlgorithmParameterException {
AlgorithmParameterSpec algSpecificSpec = mSpec.getAlgorithmParameterSpec();
switch (mKeymasterAlgorithm) {
- case KeymasterDefs.KM_ALGORITHM_RSA:
- {
+ case KeymasterDefs.KM_ALGORITHM_RSA: {
BigInteger publicExponent = null;
if (algSpecificSpec instanceof RSAKeyGenParameterSpec) {
RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) algSpecificSpec;
@@ -474,7 +492,7 @@
publicExponent = rsaSpec.getPublicExponent();
} else if (algSpecificSpec != null) {
throw new InvalidAlgorithmParameterException(
- "RSA may only use RSAKeyGenParameterSpec");
+ "RSA may only use RSAKeyGenParameterSpec");
}
if (publicExponent == null) {
publicExponent = RSAKeyGenParameterSpec.F4;
@@ -487,7 +505,8 @@
|| (publicExponent.compareTo(KeymasterArguments.UINT64_MAX_VALUE) > 0)) {
throw new InvalidAlgorithmParameterException(
"Unsupported RSA public exponent: " + publicExponent
- + ". Maximum supported value: " + KeymasterArguments.UINT64_MAX_VALUE);
+ + ". Maximum supported value: "
+ + KeymasterArguments.UINT64_MAX_VALUE);
}
mRSAPublicExponent = publicExponent.longValue();
break;
@@ -501,7 +520,7 @@
if (ecSpecKeySizeBits == null) {
throw new InvalidAlgorithmParameterException(
"Unsupported EC curve name: " + curveName
- + ". Supported: " + SUPPORTED_EC_NIST_CURVE_NAMES);
+ + ". Supported: " + SUPPORTED_EC_NIST_CURVE_NAMES);
}
if (mKeySizeBits == -1) {
mKeySizeBits = ecSpecKeySizeBits;
@@ -512,7 +531,7 @@
}
} else if (algSpecificSpec != null) {
throw new InvalidAlgorithmParameterException(
- "EC may only use ECGenParameterSpec");
+ "EC may only use ECGenParameterSpec");
}
break;
default:
@@ -546,7 +565,7 @@
final int flags =
mSpec.isCriticalToDeviceEncryption()
? IKeystoreSecurityLevel
- .KEY_FLAG_AUTH_BOUND_WITHOUT_CRYPTOGRAPHIC_LSKF_BINDING
+ .KEY_FLAG_AUTH_BOUND_WITHOUT_CRYPTOGRAPHIC_LSKF_BINDING
: 0;
byte[] additionalEntropy =
@@ -585,7 +604,7 @@
success = true;
return new KeyPair(publicKey, publicKey.getPrivateKey());
} catch (android.security.KeyStoreException e) {
- switch(e.getErrorCode()) {
+ switch (e.getErrorCode()) {
case KeymasterDefs.KM_ERROR_HARDWARE_TYPE_UNAVAILABLE:
throw new StrongBoxUnavailableException("Failed to generated key pair.", e);
case ResponseCode.OUT_OF_KEYS:
@@ -605,7 +624,7 @@
throw p;
}
} catch (UnrecoverableKeyException | IllegalArgumentException
- | DeviceIdAttestationException e) {
+ | DeviceIdAttestationException | InvalidAlgorithmParameterException e) {
throw new ProviderException(
"Failed to construct key object from newly generated key pair.", e);
} finally {
@@ -666,8 +685,8 @@
if (idTypesSet.contains(AttestationUtils.ID_TYPE_IMEI)
|| idTypesSet.contains(AttestationUtils.ID_TYPE_MEID)) {
telephonyService =
- (TelephonyManager) android.app.AppGlobals.getInitialApplication()
- .getSystemService(Context.TELEPHONY_SERVICE);
+ (TelephonyManager) android.app.AppGlobals.getInitialApplication()
+ .getSystemService(Context.TELEPHONY_SERVICE);
if (telephonyService == null) {
throw new DeviceIdAttestationException("Unable to access telephony service");
}
@@ -715,12 +734,20 @@
}
private Collection<KeyParameter> constructKeyGenerationArguments()
- throws DeviceIdAttestationException, IllegalArgumentException {
+ throws DeviceIdAttestationException, IllegalArgumentException,
+ InvalidAlgorithmParameterException {
List<KeyParameter> params = new ArrayList<>();
params.add(KeyStore2ParameterUtils.makeInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits));
params.add(KeyStore2ParameterUtils.makeEnum(
KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm
));
+
+ if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_EC) {
+ params.add(KeyStore2ParameterUtils.makeEnum(
+ Tag.EC_CURVE, keySize2EcCurve(mKeySizeBits)
+ ));
+ }
+
ArrayUtils.forEach(mKeymasterPurposes, (purpose) -> {
params.add(KeyStore2ParameterUtils.makeEnum(
KeymasterDefs.KM_TAG_PURPOSE, purpose
@@ -844,7 +871,7 @@
if (isStrongBoxBacked && keySize != 256) {
throw new InvalidAlgorithmParameterException(
"Unsupported StrongBox EC key size: "
- + keySize + " bits. Supported: 256");
+ + keySize + " bits. Supported: 256");
}
if (!SUPPORTED_EC_NIST_CURVE_SIZES.contains(keySize)) {
throw new InvalidAlgorithmParameterException("Unsupported EC key size: "
@@ -892,8 +919,7 @@
return null;
}
switch (keymasterAlgorithm) {
- case KeymasterDefs.KM_ALGORITHM_EC:
- {
+ case KeymasterDefs.KM_ALGORITHM_EC: {
Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests(
spec.getDigests(),
AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests());
@@ -940,8 +966,7 @@
return KeyProperties.Digest.fromKeymasterToSignatureAlgorithmDigest(
bestKeymasterDigest) + "WithECDSA";
}
- case KeymasterDefs.KM_ALGORITHM_RSA:
- {
+ case KeymasterDefs.KM_ALGORITHM_RSA: {
// Check whether this key is authorized for PKCS#1 signature padding.
// We use Bouncy Castle to generate self-signed RSA certificates. Bouncy Castle
// only supports RSA certificates signed using PKCS#1 padding scheme. The key needs
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
index 0af8d24..aa66653 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
@@ -46,7 +46,7 @@
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"以 30% 的螢幕空間顯示頂端畫面"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"以全螢幕顯示底部畫面"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"使用單手模式"</string>
- <string name="one_handed_tutorial_description" msgid="3486582858591353067">"如要退出,請從螢幕底部向上滑動,或輕觸應用程式上的任何位置"</string>
+ <string name="one_handed_tutorial_description" msgid="3486582858591353067">"如要退出,請從螢幕底部向上滑動,或輕觸應用程式上方的任何位置"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"啟動單手模式"</string>
<string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"結束單手模式"</string>
<string name="bubbles_settings_button_description" msgid="1301286017420516912">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」對話框的設定"</string>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 4b1955e..ba0ab6d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -62,7 +62,8 @@
* Unified task organizer for all components in the shell.
* TODO(b/167582004): may consider consolidating this class and TaskOrganizer
*/
-public class ShellTaskOrganizer extends TaskOrganizer {
+public class ShellTaskOrganizer extends TaskOrganizer implements
+ SizeCompatUIController.SizeCompatUICallback {
// Intentionally using negative numbers here so the positive numbers can be used
// for task id specific listeners that will be added later.
@@ -158,6 +159,9 @@
Context context, @Nullable SizeCompatUIController sizeCompatUI) {
super(taskOrganizerController, mainExecutor);
mSizeCompatUI = sizeCompatUI;
+ if (sizeCompatUI != null) {
+ sizeCompatUI.setSizeCompatUICallback(this);
+ }
}
@Override
@@ -481,6 +485,17 @@
}
}
+ @Override
+ public void onSizeCompatRestartButtonClicked(int taskId) {
+ final TaskAppearedInfo info;
+ synchronized (mLock) {
+ info = mTasks.get(taskId);
+ }
+ if (info != null) {
+ restartTaskTopActivityProcessIfVisible(info.getTaskInfo().token);
+ }
+ }
+
/**
* Notifies {@link SizeCompatUIController} about the size compat info changed on the give Task
* to update the UI accordingly.
@@ -497,15 +512,14 @@
// The task is vanished or doesn't support size compat UI, notify to remove size compat UI
// on this Task if there is any.
if (taskListener == null || !taskListener.supportSizeCompatUI()
- || !taskInfo.topActivityInSizeCompat) {
+ || !taskInfo.topActivityInSizeCompat || !taskInfo.isVisible) {
mSizeCompatUI.onSizeCompatInfoChanged(taskInfo.displayId, taskInfo.taskId,
- null /* taskConfig */, null /* sizeCompatActivity*/,
- null /* taskListener */);
+ null /* taskConfig */, null /* taskListener */);
return;
}
mSizeCompatUI.onSizeCompatInfoChanged(taskInfo.displayId, taskInfo.taskId,
- taskInfo.configuration, taskInfo.topActivityToken, taskListener);
+ taskInfo.configuration, taskListener);
}
private TaskListener getTaskListener(RunningTaskInfo runningTaskInfo) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index ef113dc..97c89d0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -134,6 +134,18 @@
}
/**
+ * Sets the accessibility window for the given {@param shellRootLayer}.
+ */
+ public void setShellRootAccessibilityWindow(int displayId,
+ @WindowManager.ShellRootLayer int shellRootLayer, View view) {
+ PerDisplay pd = mPerDisplay.get(displayId);
+ if (pd == null) {
+ return;
+ }
+ pd.setShellRootAccessibilityWindow(shellRootLayer, view);
+ }
+
+ /**
* Sets the touchable region of a view's window. This will be cropped to the window size.
* @param view
* @param region
@@ -202,15 +214,9 @@
attrs.flags |= FLAG_HARDWARE_ACCELERATED;
viewRoot.setView(view, attrs);
mViewRoots.put(view, viewRoot);
-
- try {
- mWmService.setShellRootAccessibilityWindow(mDisplayId, shellRootLayer,
- viewRoot.getWindowToken());
- } catch (RemoteException e) {
- Slog.e(TAG, "Error setting accessibility window for " + mDisplayId + ":"
- + shellRootLayer, e);
- }
+ setShellRootAccessibilityWindow(shellRootLayer, view);
}
+
SysUiWindowManager addRoot(@WindowManager.ShellRootLayer int shellRootLayer) {
SysUiWindowManager wwm = mWwms.get(shellRootLayer);
if (wwm != null) {
@@ -240,6 +246,21 @@
return wwm.mContainerWindow;
}
+ void setShellRootAccessibilityWindow(@WindowManager.ShellRootLayer int shellRootLayer,
+ View view) {
+ SysUiWindowManager wwm = mWwms.get(shellRootLayer);
+ if (wwm == null) {
+ return;
+ }
+ try {
+ mWmService.setShellRootAccessibilityWindow(mDisplayId, shellRootLayer,
+ view != null ? mViewRoots.get(view).getWindowToken() : null);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error setting accessibility window for " + mDisplayId + ":"
+ + shellRootLayer, e);
+ }
+ }
+
void updateConfiguration(Configuration configuration) {
for (int i = 0; i < mWwms.size(); ++i) {
mWwms.valueAt(i).updateConfiguration(configuration);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
index bc8e1e7..a646b07 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
@@ -524,6 +524,15 @@
mListeners.forEach(l -> l.onPipMenuStateChangeFinish(menuState));
}
mMenuState = menuState;
+ switch (mMenuState) {
+ case MENU_STATE_NONE:
+ mSystemWindows.setShellRootAccessibilityWindow(0, SHELL_ROOT_LAYER_PIP, null);
+ break;
+ default:
+ mSystemWindows.setShellRootAccessibilityWindow(0, SHELL_ROOT_LAYER_PIP,
+ mPipMenuView);
+ break;
+ }
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java
index c981ade..1fc4d12 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java
@@ -20,7 +20,6 @@
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.display.DisplayManager;
-import android.os.IBinder;
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
@@ -45,6 +44,13 @@
*/
public class SizeCompatUIController implements DisplayController.OnDisplaysChangedListener,
DisplayImeController.ImePositionProcessor {
+
+ /** Callback for size compat UI interaction. */
+ public interface SizeCompatUICallback {
+ /** Called when the size compat restart button is clicked. */
+ void onSizeCompatRestartButtonClicked(int taskId);
+ }
+
private static final String TAG = "SizeCompatUIController";
/** Whether the IME is shown on display id. */
@@ -61,6 +67,8 @@
private final DisplayImeController mImeController;
private final SyncTransactionQueue mSyncQueue;
+ private SizeCompatUICallback mCallback;
+
/** Only show once automatically in the process life. */
private boolean mHasShownHint;
@@ -76,29 +84,31 @@
mImeController.addPositionProcessor(this);
}
+ /** Sets the callback for UI interactions. */
+ public void setSizeCompatUICallback(SizeCompatUICallback callback) {
+ mCallback = callback;
+ }
+
/**
* Called when the Task info changed. Creates and updates the size compat UI if there is an
* activity in size compat, or removes the UI if there is no size compat activity.
- *
* @param displayId display the task and activity are in.
* @param taskId task the activity is in.
* @param taskConfig task config to place the size compat UI with.
- * @param sizeCompatActivity the size compat activity in the task. Can be {@code null} if the
- * top activity in this Task is not in size compat.
* @param taskListener listener to handle the Task Surface placement.
*/
public void onSizeCompatInfoChanged(int displayId, int taskId,
- @Nullable Configuration taskConfig, @Nullable IBinder sizeCompatActivity,
+ @Nullable Configuration taskConfig,
@Nullable ShellTaskOrganizer.TaskListener taskListener) {
- if (taskConfig == null || sizeCompatActivity == null || taskListener == null) {
+ if (taskConfig == null || taskListener == null) {
// Null token means the current foreground activity is not in size compatibility mode.
removeLayout(taskId);
} else if (mActiveLayouts.contains(taskId)) {
// UI already exists, update the UI layout.
- updateLayout(taskId, taskConfig, sizeCompatActivity, taskListener);
+ updateLayout(taskId, taskConfig, taskListener);
} else {
// Create a new size compat UI.
- createLayout(displayId, taskId, taskConfig, sizeCompatActivity, taskListener);
+ createLayout(displayId, taskId, taskConfig, taskListener);
}
}
@@ -137,7 +147,7 @@
}
private void createLayout(int displayId, int taskId, Configuration taskConfig,
- IBinder activityToken, ShellTaskOrganizer.TaskListener taskListener) {
+ ShellTaskOrganizer.TaskListener taskListener) {
final Context context = getOrCreateDisplayContext(displayId);
if (context == null) {
Log.e(TAG, "Cannot get context for display " + displayId);
@@ -145,17 +155,16 @@
}
final SizeCompatUILayout layout = createLayout(context, displayId, taskId, taskConfig,
- activityToken, taskListener);
+ taskListener);
mActiveLayouts.put(taskId, layout);
layout.createSizeCompatButton(isImeShowingOnDisplay(displayId));
}
@VisibleForTesting
SizeCompatUILayout createLayout(Context context, int displayId, int taskId,
- Configuration taskConfig, IBinder activityToken,
- ShellTaskOrganizer.TaskListener taskListener) {
- final SizeCompatUILayout layout = new SizeCompatUILayout(mSyncQueue, context, taskConfig,
- taskId, activityToken, taskListener, mDisplayController.getDisplayLayout(displayId),
+ Configuration taskConfig, ShellTaskOrganizer.TaskListener taskListener) {
+ final SizeCompatUILayout layout = new SizeCompatUILayout(mSyncQueue, mCallback, context,
+ taskConfig, taskId, taskListener, mDisplayController.getDisplayLayout(displayId),
mHasShownHint);
// Only show hint for the first time.
mHasShownHint = true;
@@ -163,13 +172,12 @@
}
private void updateLayout(int taskId, Configuration taskConfig,
- IBinder sizeCompatActivity,
ShellTaskOrganizer.TaskListener taskListener) {
final SizeCompatUILayout layout = mActiveLayouts.get(taskId);
if (layout == null) {
return;
}
- layout.updateSizeCompatInfo(taskConfig, sizeCompatActivity, taskListener,
+ layout.updateSizeCompatInfo(taskConfig, taskListener,
isImeShowingOnDisplay(layout.getDisplayId()));
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java
index c6d994e..a5e96d1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java
@@ -23,13 +23,11 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import android.annotation.Nullable;
-import android.app.ActivityClient;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Binder;
-import android.os.IBinder;
import android.view.SurfaceControl;
import android.view.View;
import android.view.WindowManager;
@@ -48,11 +46,11 @@
private static final String TAG = "SizeCompatUILayout";
private final SyncTransactionQueue mSyncQueue;
+ private final SizeCompatUIController.SizeCompatUICallback mCallback;
private Context mContext;
private Configuration mTaskConfig;
private final int mDisplayId;
private final int mTaskId;
- private IBinder mActivityToken;
private ShellTaskOrganizer.TaskListener mTaskListener;
private DisplayLayout mDisplayLayout;
@@ -72,15 +70,16 @@
final int mPopupOffsetY;
boolean mShouldShowHint;
- SizeCompatUILayout(SyncTransactionQueue syncQueue, Context context, Configuration taskConfig,
- int taskId, IBinder activityToken, ShellTaskOrganizer.TaskListener taskListener,
+ SizeCompatUILayout(SyncTransactionQueue syncQueue,
+ SizeCompatUIController.SizeCompatUICallback callback, Context context,
+ Configuration taskConfig, int taskId, ShellTaskOrganizer.TaskListener taskListener,
DisplayLayout displayLayout, boolean hasShownHint) {
mSyncQueue = syncQueue;
+ mCallback = callback;
mContext = context.createConfigurationContext(taskConfig);
mTaskConfig = taskConfig;
mDisplayId = mContext.getDisplayId();
mTaskId = taskId;
- mActivityToken = activityToken;
mTaskListener = taskListener;
mDisplayLayout = displayLayout;
mShouldShowHint = !hasShownHint;
@@ -141,12 +140,11 @@
}
/** Called when size compat info changed. */
- void updateSizeCompatInfo(Configuration taskConfig, IBinder activityToken,
+ void updateSizeCompatInfo(Configuration taskConfig,
ShellTaskOrganizer.TaskListener taskListener, boolean isImeShowing) {
final Configuration prevTaskConfig = mTaskConfig;
final ShellTaskOrganizer.TaskListener prevTaskListener = mTaskListener;
mTaskConfig = taskConfig;
- mActivityToken = activityToken;
mTaskListener = taskListener;
// Update configuration.
@@ -253,7 +251,7 @@
/** Called when the restart button is clicked. */
void onRestartButtonClicked() {
- ActivityClient.getInstance().restartActivityProcessIfVisible(mActivityToken);
+ mCallback.onSizeCompatRestartButtonClicked(mTaskId);
}
/** Called when the restart button is long clicked. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index b09d0d8..75dd561 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -18,6 +18,9 @@
import static android.os.Process.THREAD_PRIORITY_TOP_APP_BOOST;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
import android.annotation.ColorInt;
import android.annotation.NonNull;
@@ -47,6 +50,7 @@
import android.view.SurfaceControl;
import android.view.View;
import android.window.SplashScreenView;
+import android.window.StartingWindowInfo.StartingWindowType;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -122,17 +126,17 @@
* view on background thread so the view and the drawable can be create and pre-draw in
* parallel.
*
- * @param emptyView Create a splash screen view without icon on it.
+ * @param suggestType Suggest type to create the splash screen view.
* @param consumer Receiving the SplashScreenView object, which will also be executed
* on splash screen thread. Note that the view can be null if failed.
*/
- void createContentView(Context context, boolean emptyView, ActivityInfo info, int taskId,
- Consumer<SplashScreenView> consumer) {
+ void createContentView(Context context, @StartingWindowType int suggestType, ActivityInfo info,
+ int taskId, Consumer<SplashScreenView> consumer) {
mSplashscreenWorkerHandler.post(() -> {
SplashScreenView contentView;
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "makeSplashScreenContentView");
- contentView = makeSplashScreenContentView(context, info, emptyView);
+ contentView = makeSplashScreenContentView(context, info, suggestType);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
} catch (RuntimeException e) {
Slog.w(TAG, "failed creating starting window content at taskId: "
@@ -199,22 +203,45 @@
}
}
+ private static Drawable peekLegacySplashscreenContent(Context context,
+ SplashScreenWindowAttrs attrs) {
+ final TypedArray a = context.obtainStyledAttributes(R.styleable.Window);
+ final int resId = safeReturnAttrDefault((def) ->
+ a.getResourceId(R.styleable.Window_windowSplashscreenContent, def), 0);
+ a.recycle();
+ if (resId != 0) {
+ return context.getDrawable(resId);
+ }
+ if (attrs.mWindowBgResId != 0) {
+ return context.getDrawable(attrs.mWindowBgResId);
+ }
+ return null;
+ }
+
private SplashScreenView makeSplashScreenContentView(Context context, ActivityInfo ai,
- boolean emptyView) {
+ @StartingWindowType int suggestType) {
updateDensity();
getWindowAttrs(context, mTmpAttrs);
mLastPackageContextConfigHash = context.getResources().getConfiguration().hashCode();
- final int themeBGColor = mColorCache.getWindowColor(ai.packageName,
- mLastPackageContextConfigHash, mTmpAttrs.mWindowBgColor, mTmpAttrs.mWindowBgResId,
- () -> peekWindowBGColor(context, mTmpAttrs)).mBgColor;
- // TODO (b/173975965) Tracking the performance on improved splash screen.
+
+ final Drawable legacyDrawable = suggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
+ ? peekLegacySplashscreenContent(context, mTmpAttrs) : null;
+ final int themeBGColor = legacyDrawable != null
+ ? getBGColorFromCache(ai, () -> estimateWindowBGColor(legacyDrawable))
+ : getBGColorFromCache(ai, () -> peekWindowBGColor(context, mTmpAttrs));
return new StartingWindowViewBuilder(context, ai)
.setWindowBGColor(themeBGColor)
- .makeEmptyView(emptyView)
+ .overlayDrawable(legacyDrawable)
+ .chooseStyle(suggestType)
.build();
}
+ private int getBGColorFromCache(ActivityInfo ai, IntSupplier windowBgColorSupplier) {
+ return mColorCache.getWindowColor(ai.packageName, mLastPackageContextConfigHash,
+ mTmpAttrs.mWindowBgColor, mTmpAttrs.mWindowBgResId, windowBgColorSupplier).mBgColor;
+ }
+
private static <T> T safeReturnAttrDefault(UnaryOperator<T> getMethod, T def) {
try {
return getMethod.apply(def);
@@ -267,7 +294,8 @@
private final Context mContext;
private final ActivityInfo mActivityInfo;
- private boolean mEmptyView;
+ private Drawable mOverlayDrawable;
+ private int mSuggestType;
private int mThemeColor;
private Drawable mFinalIconDrawable;
private int mFinalIconSize = mIconSize;
@@ -282,16 +310,22 @@
return this;
}
- StartingWindowViewBuilder makeEmptyView(boolean empty) {
- mEmptyView = empty;
+ StartingWindowViewBuilder overlayDrawable(Drawable overlay) {
+ mOverlayDrawable = overlay;
+ return this;
+ }
+
+ StartingWindowViewBuilder chooseStyle(int suggestType) {
+ mSuggestType = suggestType;
return this;
}
SplashScreenView build() {
Drawable iconDrawable;
final int animationDuration;
- if (mEmptyView) {
- // empty splash screen case
+ if (mSuggestType == STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN
+ || mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
+ // empty or legacy splash screen case
animationDuration = 0;
mFinalIconSize = 0;
} else if (mTmpAttrs.mSplashScreenIcon != null) {
@@ -403,13 +437,15 @@
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "fillViewWithIcon");
final SplashScreenView.Builder builder = new SplashScreenView.Builder(mContext);
builder.setBackgroundColor(mThemeColor);
+ builder.setOverlayDrawable(mOverlayDrawable);
if (iconDrawable != null) {
builder.setIconSize(iconSize)
.setIconBackground(mTmpAttrs.mIconBgColor)
.setCenterViewDrawable(iconDrawable)
.setAnimationDurationMillis(animationDuration);
}
- if (mTmpAttrs.mBrandingImage != null) {
+ if (mSuggestType == STARTING_WINDOW_TYPE_SPLASH_SCREEN
+ && mTmpAttrs.mBrandingImage != null) {
builder.setBrandingDrawable(mTmpAttrs.mBrandingImage, mBrandingImageWidth,
mBrandingImageHeight);
}
@@ -417,20 +453,22 @@
if (DEBUG) {
Slog.d(TAG, "fillViewWithIcon surfaceWindowView " + splashScreenView);
}
- if (mEmptyView) {
- splashScreenView.setNotCopyable();
- }
- splashScreenView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
- @Override
- public void onViewAttachedToWindow(View v) {
- SplashScreenView.applySystemBarsContrastColor(v.getWindowInsetsController(),
- splashScreenView.getInitBackgroundColor());
- }
+ if (mSuggestType != STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
+ splashScreenView.addOnAttachStateChangeListener(
+ new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ SplashScreenView.applySystemBarsContrastColor(
+ v.getWindowInsetsController(),
+ splashScreenView.getInitBackgroundColor());
+ }
- @Override
- public void onViewDetachedFromWindow(View v) {
- }
- });
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ }
+ });
+ }
+
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
return splashScreenView;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index 670af96..4dc5447 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -20,6 +20,8 @@
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Choreographer.CALLBACK_INSETS_ANIMATION;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
import android.annotation.Nullable;
import android.app.ActivityManager.RunningTaskInfo;
@@ -32,7 +34,6 @@
import android.content.res.TypedArray;
import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
import android.hardware.display.DisplayManager;
import android.os.IBinder;
import android.os.RemoteCallback;
@@ -50,6 +51,7 @@
import android.window.SplashScreenView;
import android.window.SplashScreenView.SplashScreenViewParcelable;
import android.window.StartingWindowInfo;
+import android.window.StartingWindowInfo.StartingWindowType;
import android.window.TaskSnapshot;
import com.android.internal.R;
@@ -149,10 +151,11 @@
/**
* Called when a task need a splash screen starting window.
- * @param emptyView Whether drawing an empty frame without anything on it.
+ *
+ * @param suggestType The suggestion type to draw the splash screen.
*/
void addSplashScreenStartingWindow(StartingWindowInfo windowInfo, IBinder appToken,
- boolean emptyView) {
+ @StartingWindowType int suggestType) {
final RunningTaskInfo taskInfo = windowInfo.taskInfo;
final ActivityInfo activityInfo = taskInfo.topActivityInfo;
if (activityInfo == null) {
@@ -173,7 +176,8 @@
: com.android.internal.R.style.Theme_DeviceDefault_DayNight;
if (DEBUG_SPLASH_SCREEN) {
Slog.d(TAG, "addSplashScreen " + activityInfo.packageName
- + " theme=" + Integer.toHexString(theme) + " task= " + taskInfo.taskId);
+ + " theme=" + Integer.toHexString(theme) + " task=" + taskInfo.taskId
+ + " suggestType=" + suggestType);
}
// Obtain proper context to launch on the right display.
@@ -231,13 +235,19 @@
params.setFitInsetsTypes(0);
params.format = PixelFormat.TRANSLUCENT;
int windowFlags = WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
- | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
final TypedArray a = context.obtainStyledAttributes(R.styleable.Window);
if (a.getBoolean(R.styleable.Window_windowShowWallpaper, false)) {
windowFlags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
}
+ if (suggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
+ if (a.getBoolean(R.styleable.Window_windowDrawsSystemBarBackgrounds, false)) {
+ windowFlags |= WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ }
+ } else {
+ windowFlags |= WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ }
params.layoutInDisplayCutoutMode = a.getInt(
R.styleable.Window_windowLayoutInDisplayCutoutMode,
params.layoutInDisplayCutoutMode);
@@ -289,6 +299,7 @@
final SplashScreenViewSupplier viewSupplier = new SplashScreenViewSupplier();
final FrameLayout rootLayout = new FrameLayout(context);
rootLayout.setPadding(0, 0, 0, 0);
+ rootLayout.setFitsSystemWindows(false);
final Runnable setViewSynchronized = () -> {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addSplashScreenView");
// waiting for setContentView before relayoutWindow
@@ -311,12 +322,12 @@
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
};
- mSplashscreenContentDrawer.createContentView(context, emptyView, activityInfo, taskId,
+ mSplashscreenContentDrawer.createContentView(context, suggestType, activityInfo, taskId,
viewSupplier::setView);
try {
final WindowManager wm = context.getSystemService(WindowManager.class);
- if (addWindow(taskId, appToken, rootLayout, wm, params)) {
+ if (addWindow(taskId, appToken, rootLayout, wm, params, suggestType)) {
// We use the splash screen worker thread to create SplashScreenView while adding
// the window, as otherwise Choreographer#doFrame might be delayed on this thread.
// And since Choreographer#doFrame won't happen immediately after adding the window,
@@ -336,8 +347,10 @@
int getStartingWindowBackgroundColorForTask(int taskId) {
StartingWindowRecord startingWindowRecord = mStartingWindowRecords.get(taskId);
- if (startingWindowRecord == null || startingWindowRecord.mContentView == null) return 0;
- return ((ColorDrawable) startingWindowRecord.mContentView.getBackground()).getColor();
+ if (startingWindowRecord == null || startingWindowRecord.mContentView == null) {
+ return 0;
+ }
+ return startingWindowRecord.mContentView.getInitBackgroundColor();
}
private static class SplashScreenViewSupplier implements Supplier<SplashScreenView> {
@@ -379,7 +392,7 @@
return;
}
final StartingWindowRecord tView = new StartingWindowRecord(appToken,
- null/* decorView */, surface);
+ null/* decorView */, surface, STARTING_WINDOW_TYPE_SNAPSHOT);
mStartingWindowRecords.put(taskId, tView);
}
@@ -449,7 +462,7 @@
}
protected boolean addWindow(int taskId, IBinder appToken, View view, WindowManager wm,
- WindowManager.LayoutParams params) {
+ WindowManager.LayoutParams params, @StartingWindowType int suggestType) {
boolean shouldSaveView = true;
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addRootView");
@@ -469,14 +482,15 @@
}
if (shouldSaveView) {
removeWindowNoAnimate(taskId);
- saveSplashScreenRecord(appToken, taskId, view);
+ saveSplashScreenRecord(appToken, taskId, view, suggestType);
}
return shouldSaveView;
}
- private void saveSplashScreenRecord(IBinder appToken, int taskId, View view) {
+ private void saveSplashScreenRecord(IBinder appToken, int taskId, View view,
+ @StartingWindowType int suggestType) {
final StartingWindowRecord tView = new StartingWindowRecord(appToken, view,
- null/* TaskSnapshotWindow */);
+ null/* TaskSnapshotWindow */, suggestType);
mStartingWindowRecords.put(taskId, tView);
}
@@ -493,14 +507,18 @@
Slog.v(TAG, "Removing splash screen window for task: " + taskId);
}
if (record.mContentView != null) {
- if (playRevealAnimation) {
- mSplashscreenContentDrawer.applyExitAnimation(record.mContentView,
- leash, frame,
- () -> removeWindowInner(record.mDecorView, true));
+ if (record.mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
+ removeWindowInner(record.mDecorView, false);
} else {
- // the SplashScreenView has been copied to client, hide the view to skip
- // default exit animation
- removeWindowInner(record.mDecorView, true);
+ if (playRevealAnimation) {
+ mSplashscreenContentDrawer.applyExitAnimation(record.mContentView,
+ leash, frame,
+ () -> removeWindowInner(record.mDecorView, true));
+ } else {
+ // the SplashScreenView has been copied to client, hide the view to skip
+ // default exit animation
+ removeWindowInner(record.mDecorView, true);
+ }
}
} else {
// shouldn't happen
@@ -537,6 +555,7 @@
private final TaskSnapshotWindow mTaskSnapshotWindow;
private SplashScreenView mContentView;
private boolean mSetSplashScreen;
+ private @StartingWindowType int mSuggestType;
StartingWindowRecord(IBinder appToken, View decorView,
TaskSnapshotWindow taskSnapshotWindow) {
@@ -545,6 +564,14 @@
mTaskSnapshotWindow = taskSnapshotWindow;
}
+ StartingWindowRecord(IBinder appToken, View decorView,
+ TaskSnapshotWindow taskSnapshotWindow, @StartingWindowType int suggestType) {
+ mAppToken = appToken;
+ mDecorView = decorView;
+ mTaskSnapshotWindow = taskSnapshotWindow;
+ mSuggestType = suggestType;
+ }
+
private void setSplashScreenView(SplashScreenView splashScreenView) {
if (mSetSplashScreen) {
return;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
index 9c1dde9..eaa89d8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
@@ -17,6 +17,7 @@
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
@@ -31,6 +32,7 @@
import android.util.Slog;
import android.view.SurfaceControl;
import android.window.StartingWindowInfo;
+import android.window.StartingWindowInfo.StartingWindowType;
import android.window.TaskOrganizer;
import android.window.TaskSnapshot;
@@ -106,10 +108,6 @@
mTaskLaunchingCallback = listener;
}
- private boolean shouldSendToListener(int suggestionType) {
- return suggestionType != STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN;
- }
-
/**
* Called when a task need a starting window.
*/
@@ -120,12 +118,9 @@
final int suggestionType = mStartingWindowTypeAlgorithm.getSuggestedWindowType(
windowInfo);
final RunningTaskInfo runningTaskInfo = windowInfo.taskInfo;
- if (suggestionType == STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
+ if (isSplashScreenType(suggestionType)) {
mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken,
- false /* emptyView */);
- } else if (suggestionType == STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN) {
- mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken,
- true /* emptyView */);
+ suggestionType);
} else if (suggestionType == STARTING_WINDOW_TYPE_SNAPSHOT) {
final TaskSnapshot snapshot = windowInfo.mTaskSnapshot;
mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken,
@@ -133,7 +128,7 @@
} else /* suggestionType == STARTING_WINDOW_TYPE_NONE */ {
// Don't add a staring window.
}
- if (mTaskLaunchingCallback != null && shouldSendToListener(suggestionType)) {
+ if (mTaskLaunchingCallback != null && isSplashScreenType(suggestionType)) {
int taskId = runningTaskInfo.taskId;
int color = mStartingSurfaceDrawer.getStartingWindowBackgroundColorForTask(taskId);
mTaskLaunchingCallback.accept(taskId, suggestionType, color);
@@ -143,6 +138,12 @@
});
}
+ private static boolean isSplashScreenType(@StartingWindowType int suggestionType) {
+ return suggestionType == STARTING_WINDOW_TYPE_SPLASH_SCREEN
+ || suggestionType == STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN
+ || suggestionType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
+ }
+
public void copySplashScreenView(int taskId) {
mSplashScreenExecutor.execute(() -> {
mStartingSurfaceDrawer.copySplashScreenView(taskId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
index 5a134b8..848eff4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
@@ -18,11 +18,13 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_NONE;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_LEGACY_SPLASH_SCREEN;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
@@ -54,30 +56,38 @@
final boolean activityCreated = (parameter & TYPE_PARAMETER_ACTIVITY_CREATED) != 0;
final boolean useEmptySplashScreen =
(parameter & TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN) != 0;
+ final boolean legacySplashScreen =
+ ((parameter & TYPE_PARAMETER_LEGACY_SPLASH_SCREEN) != 0);
final boolean topIsHome = windowInfo.taskInfo.topActivityType == ACTIVITY_TYPE_HOME;
if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
- Slog.d(TAG, "preferredStartingWindowType newTask " + newTask
- + " taskSwitch " + taskSwitch
- + " processRunning " + processRunning
- + " allowTaskSnapshot " + allowTaskSnapshot
- + " activityCreated " + activityCreated
- + " useEmptySplashScreen " + useEmptySplashScreen
- + " topIsHome " + topIsHome);
+ Slog.d(TAG, "preferredStartingWindowType newTask:" + newTask
+ + " taskSwitch:" + taskSwitch
+ + " processRunning:" + processRunning
+ + " allowTaskSnapshot:" + allowTaskSnapshot
+ + " activityCreated:" + activityCreated
+ + " useEmptySplashScreen:" + useEmptySplashScreen
+ + " legacySplashScreen:" + legacySplashScreen
+ + " topIsHome:" + topIsHome);
}
+
+ final int visibleSplashScreenType = legacySplashScreen
+ ? STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
+ : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+
if (!topIsHome) {
if (!processRunning) {
return useEmptySplashScreen
? STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN
- : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+ : visibleSplashScreenType;
}
if (newTask) {
return useEmptySplashScreen
? STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN
- : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+ : visibleSplashScreenType;
}
if (taskSwitch && !activityCreated) {
- return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+ return visibleSplashScreenType;
}
}
if (taskSwitch && allowTaskSnapshot) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index df0a856..6b74b62 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
@@ -48,6 +48,7 @@
import android.window.ITaskOrganizer;
import android.window.ITaskOrganizerController;
import android.window.TaskAppearedInfo;
+import android.window.WindowContainerToken;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -289,7 +290,6 @@
public void testOnSizeCompatActivityChanged() {
final RunningTaskInfo taskInfo1 = createTaskInfo(12, WINDOWING_MODE_FULLSCREEN);
taskInfo1.displayId = DEFAULT_DISPLAY;
- taskInfo1.topActivityToken = mock(IBinder.class);
taskInfo1.topActivityInSizeCompat = false;
final TrackingTaskListener taskListener = new TrackingTaskListener();
mOrganizer.addListenerForType(taskListener, TASK_LISTENER_TYPE_FULLSCREEN);
@@ -297,23 +297,34 @@
// sizeCompatActivity is null if top activity is not in size compat.
verify(mSizeCompatUI).onSizeCompatInfoChanged(taskInfo1.displayId, taskInfo1.taskId,
- null /* taskConfig */, null /* sizeCompatActivity*/, null /* taskListener */);
+ null /* taskConfig */, null /* taskListener */);
// sizeCompatActivity is non-null if top activity is in size compat.
clearInvocations(mSizeCompatUI);
final RunningTaskInfo taskInfo2 =
createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode());
taskInfo2.displayId = taskInfo1.displayId;
- taskInfo2.topActivityToken = taskInfo1.topActivityToken;
taskInfo2.topActivityInSizeCompat = true;
+ taskInfo2.isVisible = true;
mOrganizer.onTaskInfoChanged(taskInfo2);
verify(mSizeCompatUI).onSizeCompatInfoChanged(taskInfo1.displayId, taskInfo1.taskId,
- taskInfo1.configuration, taskInfo1.topActivityToken, taskListener);
+ taskInfo1.configuration, taskListener);
+
+ // Not show size compat UI if task is not visible.
+ clearInvocations(mSizeCompatUI);
+ final RunningTaskInfo taskInfo3 =
+ createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode());
+ taskInfo3.displayId = taskInfo1.displayId;
+ taskInfo3.topActivityInSizeCompat = true;
+ taskInfo3.isVisible = false;
+ mOrganizer.onTaskInfoChanged(taskInfo3);
+ verify(mSizeCompatUI).onSizeCompatInfoChanged(taskInfo1.displayId, taskInfo1.taskId,
+ null /* taskConfig */, null /* taskListener */);
clearInvocations(mSizeCompatUI);
mOrganizer.onTaskVanished(taskInfo1);
verify(mSizeCompatUI).onSizeCompatInfoChanged(taskInfo1.displayId, taskInfo1.taskId,
- null /* taskConfig */, null /* sizeCompatActivity*/, null /* taskListener */);
+ null /* taskConfig */, null /* taskListener */);
}
@Test
@@ -433,6 +444,18 @@
assertEquals(listener.invisibleLocusTasks.size(), 0);
}
+ @Test
+ public void testOnSizeCompatRestartButtonClicked() throws RemoteException {
+ RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
+ task1.token = mock(WindowContainerToken.class);
+
+ mOrganizer.onTaskAppeared(task1, null);
+
+ mOrganizer.onSizeCompatRestartButtonClicked(task1.taskId);
+
+ verify(mTaskOrganizerController).restartTaskTopActivityProcessIfVisible(task1.token);
+ }
+
private static RunningTaskInfo createTaskInfo(int taskId, int windowingMode) {
RunningTaskInfo taskInfo = new RunningTaskInfo();
taskInfo.taskId = taskId;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopupTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopupTest.java
index 9845d46..10fd7d7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopupTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopupTest.java
@@ -22,7 +22,6 @@
import static org.mockito.Mockito.verify;
import android.content.res.Configuration;
-import android.os.IBinder;
import android.testing.AndroidTestingRunner;
import android.view.LayoutInflater;
import android.widget.Button;
@@ -52,7 +51,7 @@
public class SizeCompatHintPopupTest extends ShellTestCase {
@Mock private SyncTransactionQueue mSyncTransactionQueue;
- @Mock private IBinder mActivityToken;
+ @Mock private SizeCompatUIController.SizeCompatUICallback mCallback;
@Mock private ShellTaskOrganizer.TaskListener mTaskListener;
@Mock private DisplayLayout mDisplayLayout;
@@ -64,8 +63,9 @@
MockitoAnnotations.initMocks(this);
final int taskId = 1;
- mLayout = new SizeCompatUILayout(mSyncTransactionQueue, mContext, new Configuration(),
- taskId, mActivityToken, mTaskListener, mDisplayLayout, false /* hasShownHint*/);
+ mLayout = new SizeCompatUILayout(mSyncTransactionQueue, mCallback, mContext,
+ new Configuration(), taskId, mTaskListener, mDisplayLayout,
+ false /* hasShownHint */);
mHint = (SizeCompatHintPopup)
LayoutInflater.from(mContext).inflate(R.layout.size_compat_mode_hint, null);
mHint.inject(mLayout);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButtonTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButtonTest.java
index 5a43925..a20a5e9 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButtonTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButtonTest.java
@@ -22,7 +22,6 @@
import static org.mockito.Mockito.verify;
import android.content.res.Configuration;
-import android.os.IBinder;
import android.testing.AndroidTestingRunner;
import android.view.LayoutInflater;
import android.widget.ImageButton;
@@ -51,8 +50,10 @@
@SmallTest
public class SizeCompatRestartButtonTest extends ShellTestCase {
+ private static final int TASK_ID = 1;
+
@Mock private SyncTransactionQueue mSyncTransactionQueue;
- @Mock private IBinder mActivityToken;
+ @Mock private SizeCompatUIController.SizeCompatUICallback mCallback;
@Mock private ShellTaskOrganizer.TaskListener mTaskListener;
@Mock private DisplayLayout mDisplayLayout;
@@ -63,9 +64,9 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
- final int taskId = 1;
- mLayout = new SizeCompatUILayout(mSyncTransactionQueue, mContext, new Configuration(),
- taskId, mActivityToken, mTaskListener, mDisplayLayout, false /* hasShownHint*/);
+ mLayout = new SizeCompatUILayout(mSyncTransactionQueue, mCallback, mContext,
+ new Configuration(), TASK_ID, mTaskListener, mDisplayLayout,
+ false /* hasShownHint */);
mButton = (SizeCompatRestartButton)
LayoutInflater.from(mContext).inflate(R.layout.size_compat_ui, null);
mButton.inject(mLayout);
@@ -75,12 +76,11 @@
@Test
public void testOnClick() {
- doNothing().when(mLayout).onRestartButtonClicked();
-
final ImageButton button = mButton.findViewById(R.id.size_compat_restart_button);
button.performClick();
verify(mLayout).onRestartButtonClicked();
+ verify(mCallback).onSizeCompatRestartButtonClicked(TASK_ID);
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUIControllerTest.java
index 806a90b..8839f58 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUIControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUIControllerTest.java
@@ -27,7 +27,6 @@
import android.content.Context;
import android.content.res.Configuration;
-import android.os.IBinder;
import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest;
@@ -61,7 +60,6 @@
private @Mock DisplayController mMockDisplayController;
private @Mock DisplayLayout mMockDisplayLayout;
private @Mock DisplayImeController mMockImeController;
- private @Mock IBinder mMockActivityToken;
private @Mock ShellTaskOrganizer.TaskListener mMockTaskListener;
private @Mock SyncTransactionQueue mMockSyncQueue;
private @Mock SizeCompatUILayout mMockLayout;
@@ -77,8 +75,7 @@
mMockImeController, mMockSyncQueue) {
@Override
SizeCompatUILayout createLayout(Context context, int displayId, int taskId,
- Configuration taskConfig, IBinder activityToken,
- ShellTaskOrganizer.TaskListener taskListener) {
+ Configuration taskConfig, ShellTaskOrganizer.TaskListener taskListener) {
return mMockLayout;
}
};
@@ -97,21 +94,21 @@
// Verify that the restart button is added with non-null size compat info.
mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig,
- mMockActivityToken, mMockTaskListener);
+ mMockTaskListener);
verify(mController).createLayout(any(), eq(DISPLAY_ID), eq(TASK_ID), eq(taskConfig),
- eq(mMockActivityToken), eq(mMockTaskListener));
+ eq(mMockTaskListener));
// Verify that the restart button is updated with non-null new size compat info.
final Configuration newTaskConfig = new Configuration();
mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, newTaskConfig,
- mMockActivityToken, mMockTaskListener);
+ mMockTaskListener);
- verify(mMockLayout).updateSizeCompatInfo(taskConfig, mMockActivityToken, mMockTaskListener,
+ verify(mMockLayout).updateSizeCompatInfo(taskConfig, mMockTaskListener,
false /* isImeShowing */);
// Verify that the restart button is removed with null size compat info.
- mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, null, null, mMockTaskListener);
+ mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, null, mMockTaskListener);
verify(mMockLayout).release();
}
@@ -120,7 +117,7 @@
public void testOnDisplayRemoved() {
final Configuration taskConfig = new Configuration();
mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig,
- mMockActivityToken, mMockTaskListener);
+ mMockTaskListener);
mController.onDisplayRemoved(DISPLAY_ID + 1);
@@ -135,7 +132,7 @@
public void testOnDisplayConfigurationChanged() {
final Configuration taskConfig = new Configuration();
mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig,
- mMockActivityToken, mMockTaskListener);
+ mMockTaskListener);
final Configuration newTaskConfig = new Configuration();
mController.onDisplayConfigurationChanged(DISPLAY_ID + 1, newTaskConfig);
@@ -151,7 +148,7 @@
public void testChangeButtonVisibilityOnImeShowHide() {
final Configuration taskConfig = new Configuration();
mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig,
- mMockActivityToken, mMockTaskListener);
+ mMockTaskListener);
mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java
index f33cfe8..ee4c815 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java
@@ -21,20 +21,16 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import android.app.ActivityClient;
import android.content.res.Configuration;
import android.graphics.Rect;
-import android.os.IBinder;
import android.testing.AndroidTestingRunner;
import android.view.DisplayInfo;
import android.view.SurfaceControl;
@@ -66,7 +62,7 @@
private static final int TASK_ID = 1;
@Mock private SyncTransactionQueue mSyncTransactionQueue;
- @Mock private IBinder mActivityToken;
+ @Mock private SizeCompatUIController.SizeCompatUICallback mCallback;
@Mock private ShellTaskOrganizer.TaskListener mTaskListener;
@Mock private DisplayLayout mDisplayLayout;
@Mock private SizeCompatRestartButton mButton;
@@ -80,8 +76,9 @@
MockitoAnnotations.initMocks(this);
mTaskConfig = new Configuration();
- mLayout = new SizeCompatUILayout(mSyncTransactionQueue, mContext, new Configuration(),
- TASK_ID, mActivityToken, mTaskListener, mDisplayLayout, false /* hasShownHint*/);
+ mLayout = new SizeCompatUILayout(mSyncTransactionQueue, mCallback, mContext,
+ new Configuration(), TASK_ID, mTaskListener, mDisplayLayout,
+ false /* hasShownHint */);
spyOn(mLayout);
spyOn(mLayout.mButtonWindowManager);
@@ -145,7 +142,7 @@
// No diff
clearInvocations(mLayout);
- mLayout.updateSizeCompatInfo(mTaskConfig, mActivityToken, mTaskListener,
+ mLayout.updateSizeCompatInfo(mTaskConfig, mTaskListener,
false /* isImeShowing */);
verify(mLayout, never()).updateButtonSurfacePosition();
@@ -156,7 +153,7 @@
clearInvocations(mLayout);
final ShellTaskOrganizer.TaskListener newTaskListener = mock(
ShellTaskOrganizer.TaskListener.class);
- mLayout.updateSizeCompatInfo(mTaskConfig, mActivityToken, newTaskListener,
+ mLayout.updateSizeCompatInfo(mTaskConfig, newTaskListener,
false /* isImeShowing */);
verify(mLayout).release();
@@ -166,7 +163,7 @@
clearInvocations(mLayout);
final Configuration newTaskConfiguration = new Configuration();
newTaskConfiguration.windowConfiguration.setBounds(new Rect(0, 1000, 0, 2000));
- mLayout.updateSizeCompatInfo(newTaskConfiguration, mActivityToken, newTaskListener,
+ mLayout.updateSizeCompatInfo(newTaskConfiguration, newTaskListener,
false /* isImeShowing */);
verify(mLayout).updateButtonSurfacePosition();
@@ -228,12 +225,9 @@
@Test
public void testOnRestartButtonClicked() {
- spyOn(ActivityClient.getInstance());
- doNothing().when(ActivityClient.getInstance()).restartActivityProcessIfVisible(any());
-
mLayout.onRestartButtonClicked();
- verify(ActivityClient.getInstance()).restartActivityProcessIfVisible(mActivityToken);
+ verify(mCallback).onSizeCompatRestartButtonClicked(TASK_ID);
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index 903e63a..5061b23 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -15,6 +15,8 @@
*/
package com.android.wm.shell.startingsurface;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
@@ -91,7 +93,7 @@
@Override
protected boolean addWindow(int taskId, IBinder appToken,
- View view, WindowManager wm, WindowManager.LayoutParams params) {
+ View view, WindowManager wm, WindowManager.LayoutParams params, int suggestType) {
// listen for addView
mAddWindowForTask = taskId;
mViewThemeResId = view.getContext().getThemeResId();
@@ -145,9 +147,11 @@
final int taskId = 1;
final StartingWindowInfo windowInfo =
createWindowInfo(taskId, android.R.style.Theme);
- mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder, false);
+ mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder,
+ STARTING_WINDOW_TYPE_SPLASH_SCREEN);
waitHandlerIdle(mTestHandler);
- verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any());
+ verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any(),
+ eq(STARTING_WINDOW_TYPE_SPLASH_SCREEN));
assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, taskId);
mStartingSurfaceDrawer.removeStartingWindow(windowInfo.taskInfo.taskId, null, null, false);
@@ -161,9 +165,11 @@
final int taskId = 1;
final StartingWindowInfo windowInfo =
createWindowInfo(taskId, 0);
- mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder, false);
+ mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder,
+ STARTING_WINDOW_TYPE_SPLASH_SCREEN);
waitHandlerIdle(mTestHandler);
- verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any());
+ verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any(),
+ eq(STARTING_WINDOW_TYPE_SPLASH_SCREEN));
assertNotEquals(mStartingSurfaceDrawer.mViewThemeResId, 0);
}
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 81cee61..4dcd5af 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -644,6 +644,7 @@
if (mNativeSurface == nullptr) {
return;
}
+ ATRACE_CALL();
FrameInfo* forthBehind;
int64_t frameNumber;
{ // acquire lock
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
index 8b44887..c24782e 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
@@ -317,6 +317,9 @@
}
void onDeviceSelected(String callingPackage, String deviceAddress) {
+ if (callingPackage == null || deviceAddress == null) {
+ return;
+ }
mServiceCallback.complete(new Association(
getUserId(), deviceAddress, callingPackage, mRequest.getDeviceProfile(), false,
System.currentTimeMillis()));
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseFragment.java b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseFragment.java
index cfb12bc..eb8b59e 100644
--- a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseFragment.java
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/CollapsingToolbarBaseFragment.java
@@ -16,6 +16,7 @@
package com.android.settingslib.collapsingtoolbar;
+import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -55,7 +56,9 @@
@Nullable Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.collapsing_toolbar_base_layout, container,
false);
- mCoordinatorLayout = view.findViewById(R.id.content_parent);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ mCoordinatorLayout = view.findViewById(R.id.content_parent);
+ }
mCollapsingToolbarLayout = view.findViewById(R.id.collapsing_toolbar);
mAppBarLayout = view.findViewById(R.id.app_bar);
if (mCollapsingToolbarLayout != null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java
index b5f275b..b7549ec 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java
@@ -19,6 +19,7 @@
import android.annotation.SuppressLint;
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.text.TextUtils;
@@ -89,7 +90,7 @@
macAddress = macAddresses[0];
}
- if (TextUtils.isEmpty(macAddress)) {
+ if (TextUtils.isEmpty(macAddress) || macAddress.equals(WifiInfo.DEFAULT_MAC_ADDRESS)) {
mWifiMacAddress.setSummary(R.string.status_unavailable);
} else {
mWifiMacAddress.setSummary(macAddress);
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index 29fcf57..28c6166 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -35,13 +35,13 @@
android:id="@+id/animatable_clock_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:gravity="center_horizontal"
+ android:layout_gravity="start"
+ android:gravity="start"
android:textSize="@dimen/clock_text_size"
android:fontFamily="@font/clock"
- android:typeface="monospace"
android:elegantTextHeight="false"
android:singleLine="true"
+ android:fontFeatureSettings="pnum"
chargeAnimationDelay="350"
dozeWeight="200"
lockScreenWeight="400"
diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml
index c7a4829..ced155a 100644
--- a/packages/SystemUI/res-keyguard/values-ky/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml
@@ -85,7 +85,7 @@
<string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Өтө көп графикалык ачкычты тартуу аракети болду"</string>
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN-кодуңузду <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секунддан кийин дагы аракет кылып көрүңүз."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Сырсөзүңүздү <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секунддан кийин дагы аракет кылып көрүңүз."</string>
- <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Кулпуну ачуучу графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секунддан кийин дагы аракет кылып көрүңүз."</string>
+ <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Түзмөктү ачуучу графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секунддан кийин дагы аракет кылып көрүңүз."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM-картанын PIN-коду туура эмес. Эми түзмөктү бөгөттөн чыгаруу үчүн байланыш операторуңузга кайрылышыңыз керек."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">SIM-картанын PIN-коду туура эмес, сизде <xliff:g id="NUMBER_1">%d</xliff:g> аракет калды.</item>
diff --git a/packages/SystemUI/res-keyguard/values-land/dimens.xml b/packages/SystemUI/res-keyguard/values-land/dimens.xml
new file mode 100644
index 0000000..6342b9c
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/values-land/dimens.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2021, 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.
+*/
+-->
+<resources>
+ <dimen name="num_pad_row_margin_bottom">3dp</dimen>
+ <dimen name="keyguard_eca_top_margin">0dp</dimen>
+ <dimen name="keyguard_eca_bottom_margin">2dp</dimen>
+ <dimen name="keyguard_password_height">26dp</dimen>
+ <dimen name="num_pad_entry_row_margin_bottom">0dp</dimen>
+
+ <!-- The size of PIN text in the PIN unlock method. -->
+ <integer name="scaled_password_text_size">26</integer>
+</resources>
diff --git a/packages/SystemUI/res-keyguard/values-sw360dp-land/dimens.xml b/packages/SystemUI/res-keyguard/values-sw360dp-land/dimens.xml
index eb5843b..f465be4 100644
--- a/packages/SystemUI/res-keyguard/values-sw360dp-land/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-sw360dp-land/dimens.xml
@@ -23,4 +23,7 @@
<dimen name="keyguard_eca_bottom_margin">4dp</dimen>
<dimen name="keyguard_password_height">50dp</dimen>
<dimen name="num_pad_entry_row_margin_bottom">4dp</dimen>
+
+ <!-- The size of PIN text in the PIN unlock method. -->
+ <integer name="scaled_password_text_size">40</integer>
</resources>
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index e40138e..9ce83a7 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -52,6 +52,8 @@
android:paddingStart="@dimen/keyguard_indication_text_padding"
android:paddingEnd="@dimen/keyguard_indication_text_padding"
android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
+ android:maxLines="2"
+ android:ellipsize="end"
android:alpha=".8"
android:accessibilityLiveRegion="polite"
android:visibility="gone"/>
diff --git a/packages/SystemUI/res/layout/long_screenshot.xml b/packages/SystemUI/res/layout/long_screenshot.xml
index 8a2c8f0..8a3a39f 100644
--- a/packages/SystemUI/res/layout/long_screenshot.xml
+++ b/packages/SystemUI/res/layout/long_screenshot.xml
@@ -38,20 +38,21 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/preview" />
- <Button
- android:id="@+id/cancel"
- style="@android:style/Widget.DeviceDefault.Button.Colored"
- android:layout_width="wrap_content"
- android:layout_height="40dp"
- android:text="@android:string/cancel"
- android:layout_marginStart="6dp"
+ <ImageButton
+ android:id="@+id/delete"
+ style="@android:style/Widget.Material.Button.Borderless"
+ android:tint="?android:textColorPrimary"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
android:layout_marginTop="4dp"
- android:background="@drawable/screenshot_button_background"
- android:textColor="?android:textColorSecondary"
- app:layout_constraintStart_toEndOf="@id/save"
+ android:padding="12dp"
+ android:src="@drawable/ic_screenshot_delete"
+ android:scaleType="fitCenter"
+ android:contentDescription="@*android:string/delete"
+ android:tooltipText="@*android:string/delete"
+ app:layout_constraintEnd_toStartOf="@id/share"
app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@id/preview"
- />
+ app:layout_constraintBottom_toTopOf="@id/preview" />
<ImageButton
android:id="@+id/share"
@@ -159,7 +160,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@id/preview"
- app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintLeft_toLeftOf="parent"
android:scaleType="centerCrop"
android:visibility="invisible"
/>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index bb48ad5..7fc978b 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Sien onlangse boodskappe, gemiste oproepe en statusopdaterings"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Gesprek"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Onderbreek deur Moenie Steur nie"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> het \'n boodskap gestuur: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> het \'n prent gestuur"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> het \'n statusopdatering: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Kon nie jou batterymeter lees nie"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Tik vir meer inligting"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Geen wekker nie"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 1b53457..6b9e40d 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"የቅርብ ጊዜ መልዕክቶችን፣ ያመለጡ ጥሪዎች እና፣ የሁኔታ ዝመናዎችን ይመልከቱ"</string>
<string name="people_tile_title" msgid="6589377493334871272">"ውይይት"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"በአትረብሽ ባለበት ቆሟል"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> መልዕክት ልከዋል፦ <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ምስል ልኳል"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> የሁኔታ ዝማኔ አለው፦ <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"የባትሪ መለኪያዎን የማንበብ ችግር"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"ለበለጠ መረጃ መታ ያድርጉ"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"ምንም ማንቂያ አልተቀናበረም"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index fe91b68..c8aa73c 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -1170,11 +1170,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"عرض أحدث الرسائل والمكالمات الفائتة والتغييرات في الحالة"</string>
<string name="people_tile_title" msgid="6589377493334871272">"محادثة"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"تم إيقاف الإشعار مؤقتًا من خلال ميزة \"عدم الإزعاج\""</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"تم إرسال رسالة من <xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"تم إرسال صورة من <xliff:g id="NAME">%1$s</xliff:g>."</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"تم تعديل حالة <xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"حدثت مشكلة أثناء قراءة مقياس مستوى شحن البطارية."</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"انقر للحصول على مزيد من المعلومات."</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"لم يتم ضبط منبّه."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index ba6d3f4..64a466c 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"শেহতীয়া বাৰ্তা, মিছড্ কল আৰু স্থিতিৰ আপডে’ট চাওক"</string>
<string name="people_tile_title" msgid="6589377493334871272">"বাৰ্তালাপ"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"অসুবিধা নিদিব সুবিধাটোৱে পজ কৰিছে"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g>এ এটা বাৰ্তা পঠিয়াইছে: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g>এ এখন প্ৰতিচ্ছবি পঠিয়াইছে"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g>ৰ এটা স্থিতিৰ আপডে’ট আছে: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"আপোনাৰ বেটাৰী মিটাৰ পঢ়োঁতে সমস্যা হৈছে"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"অধিক তথ্যৰ বাবে টিপক"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"কোনো এলাৰ্ম ছেট কৰা হোৱা নাই"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 5cb4422..4143518 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Son mesajlar, buraxılmış zənglər və status güncəlləmələrinə baxın"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Söhbət"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"\"Narahat Etməyin\" rejimini tərəfindən durdurulub"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> mesaj göndərdi: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> şəkil göndərdi"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> status güncəlləməsi edib: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Batareya ölçüsünü oxuyarkən problem yarandı"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Ətraflı məlumat üçün toxunun"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Siqnal ayarlanmayıb"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 80652c7..a179b93 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -1152,11 +1152,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Pogledajte nedavne poruke, propuštene pozive i ažuriranja statusa"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Konverzacija"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Pauzirano režimom Ne uznemiravaj"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> je poslao/la poruku: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> šalje sliku"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ima ažuriranje statusa: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problem sa očitavanjem merača baterije"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Dodirnite za više informacija"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Alarm nije podešen"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 704c19c..83fa2af 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -1158,11 +1158,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Глядзець нядаўнія паведамленні, прапушчаныя выклікі і абнаўленні стану"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Размова"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Прыпынена функцыяй \"Не турбаваць\""</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"Карыстальнік <xliff:g id="NAME">%1$s</xliff:g> прыслаў паведамленне: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"Карыстальнік <xliff:g id="NAME">%1$s</xliff:g> адправіў відарыс"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"Карыстальнік <xliff:g id="NAME">%1$s</xliff:g> абнавіў стан: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Праблема з чытаннем індыкатара зараду акумулятара"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Націсніце, каб убачыць больш"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Няма будзільнікаў"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 2fc165e..6886ed4 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Преглеждайте скорошни съобщения, пропуснати обаждания и информация за състоянието"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Разговор"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Поставено на пауза от режима „Не безпокойте“"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> изпрати съобщение: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> изпрати изображение"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> има актуализация на състоянието: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Възникна проблем при четенето на данните за нивото на батерията"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Докоснете за още информация"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Няма зададен будилник"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 04a734d..e8a7281 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -669,9 +669,8 @@
<string name="wallet_empty_state_label" msgid="7776761245237530394">"ফোন ব্যবহার করে আরও দ্রুত ও আরও নিরাপদে কেনাকাটা করার জন্য সেট-আপ করুন"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"সবকটি দেখুন"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"পেমেন্ট করতে ডিভাইস আনলক করুন"</string>
- <!-- no translation found for wallet_secondary_label_no_card (530725155985223497) -->
- <skip />
- <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"আপডেট হচ্ছে"</string>
+ <string name="wallet_secondary_label_no_card" msgid="530725155985223497">"কার্ড যোগ করুন"</string>
+ <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"আপডেট করা হচ্ছে"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ব্যবহার করতে আনলক করুন"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"আপনার কার্ড সংক্রান্ত তথ্য পেতে সমস্যা হয়েছে, পরে আবার চেষ্টা করুন"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"লক স্ক্রিন সেটিংস"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index f1367e7..47d0773 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -1152,11 +1152,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Pregledajte nedavne poruke, propuštene pozive i ažuriranja statusa"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Razgovor"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Pauzirala je funkcija Ne ometaj"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> je poslao/la poruku: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> je poslao/la sliku"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> je ažurirao/la status: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Došlo je do problema prilikom očitavanja mjerača stanja baterije"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Dodirnite za više informacija"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nije postavljen alarm"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 1d77e0d..abcefec 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Consulta els missatges recents, les trucades perdudes i les actualitzacions d\'estat"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Conversa"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Posat en pausa pel mode No molestis"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ha enviat un missatge: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ha enviat una imatge"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> té una actualització d\'estat: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Hi ha hagut un problema en llegir el mesurador de la bateria"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Toca per obtenir més informació"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Cap alarma configurada"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 379d959..b90cff3 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -520,7 +520,7 @@
<string name="manage_notifications_text" msgid="6885645344647733116">"Spravovat"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Historie"</string>
<string name="notification_section_header_incoming" msgid="850925217908095197">"Nové"</string>
- <string name="notification_section_header_gentle" msgid="6804099527336337197">"Tiché"</string>
+ <string name="notification_section_header_gentle" msgid="6804099527336337197">"Tichá oznámení"</string>
<string name="notification_section_header_alerting" msgid="5581175033680477651">"Oznámení"</string>
<string name="notification_section_header_conversations" msgid="821834744538345661">"Konverzace"</string>
<string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Vymazat všechna tichá oznámení"</string>
@@ -735,7 +735,7 @@
<string name="inline_silent_button_keep_alerting" msgid="6577845442184724992">"Dál upozorňovat"</string>
<string name="inline_turn_off_notifications" msgid="8543989584403106071">"Vypnout oznámení"</string>
<string name="inline_keep_showing_app" msgid="4393429060390649757">"Mají se oznámení z této aplikace nadále zobrazovat?"</string>
- <string name="notification_silence_title" msgid="8608090968400832335">"Ticho"</string>
+ <string name="notification_silence_title" msgid="8608090968400832335">"Tiché"</string>
<string name="notification_alert_title" msgid="3656229781017543655">"Výchozí"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"Automaticky"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Žádný zvuk ani vibrace"</string>
@@ -748,10 +748,10 @@
<string name="notification_channel_summary_automatic_silenced" msgid="7403004439649872047">"<b>Stav:</b> priorita snížena na Tiché"</string>
<string name="notification_channel_summary_automatic_promoted" msgid="1301710305149590426">"<b>Stav:</b> zařazeno výše"</string>
<string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"<b>Stav:</b> zařazeno níže"</string>
- <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"Zobrazuje se v horní části oznámení konverzace a jako profilový obrázek na obrazovce uzamčení"</string>
- <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Zobrazuje se v horní části oznámení konverzace a jako profilový obrázek na obrazovce uzamčení, má podobu bubliny"</string>
- <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Zobrazuje se v horní části oznámení konverzace a jako profilový obrázek na obrazovce uzamčení, deaktivuje režim Nerušit"</string>
- <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Zobrazuje se v horní části oznámení konverzace a jako profilový obrázek na obrazovce uzamčení, má podobu bubliny a deaktivuje režim Nerušit"</string>
+ <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"Zobrazuje se v horní části sekce konverzací a na obrazovce uzamčení se objevuje jako profilová fotka"</string>
+ <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Zobrazuje se v horní části sekce konverzací a na obrazovce uzamčení se objevuje jako profilová fotka, má podobu bubliny"</string>
+ <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Zobrazuje se v horní části sekce konverzací a na obrazovce uzamčení se objevuje jako profilová fotka, deaktivuje režim Nerušit"</string>
+ <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Zobrazuje se v horní části sekce konverzací a na obrazovce uzamčení se objevuje jako profilová fotka, má podobu bubliny a deaktivuje režim Nerušit"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Nastavení"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priorita"</string>
<string name="no_shortcut" msgid="8257177117568230126">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> funkce konverzace nepodporuje"</string>
@@ -1158,11 +1158,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Zobrazit poslední zprávy, zmeškané hovory a aktualizace stavu"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Konverzace"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Pozastaveno funkcí Nerušit"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> posílá zprávu: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> posílá obrázek"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> má aktualizaci stavu: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problém s načtením měřiče baterie"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Klepnutím zobrazíte další informace"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Budík nenastaven"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 88731b7..cb06aa7 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Se dine seneste beskeder, mistede opkald og statusopdateringer"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Samtale"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Sat på pause af Forstyr ikke"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> har sendt en besked: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> har sendt et billede"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> har opdateret sin status: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Der er problemer med at aflæse dit batteriniveau"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Tryk for at få flere oplysninger"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Ingen alarm er indstillet"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 461c257..36e837e 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Letzte Nachrichten, verpasste Anrufe und Statusaktualisierungen ansehen"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Unterhaltung"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Durch „Bitte nicht stören“ pausiert"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> hat eine Nachricht gesendet: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> hat ein Bild gesendet"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> hat den Status aktualisiert: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problem beim Lesen des Akkustands"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Für weitere Informationen tippen"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Kein Wecker gestellt"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 98692fa..04e69f1 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Δείτε πρόσφατα μηνύματα, αναπάντητες κλήσεις και ενημερώσεις κατάστασης"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Συνομιλία"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Σε παύση από τη λειτουργία Μην ενοχλείτε"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"Ο χρήστης <xliff:g id="NAME">%1$s</xliff:g> έστειλε ένα μήνυμα: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"Ο χρήστης <xliff:g id="NAME">%1$s</xliff:g> έστειλε μια εικόνα"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"Ο χρήστης <xliff:g id="NAME">%1$s</xliff:g> έχει μια ενημέρωση κατάστασης: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Υπάρχει κάποιο πρόβλημα με την ανάγνωση του μετρητή μπαταρίας"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Πατήστε για περισσότερες πληροφορίες."</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Δεν ορίστηκε ξυπνητ."</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index fa19aab..0e1d014 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -1034,7 +1034,7 @@
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar pantalla completa"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte de la pantalla"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Botón"</string>
- <string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"El botón de accesibilidad reemplaza el gesto de accesibilidad\n\n"<annotation id="link">"Ver configuración"</annotation></string>
+ <string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"El botón de accesibilidad ha reemplazado el gesto de accesibilidad\n\n"<annotation id="link">"Ver configuración"</annotation></string>
<string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Puedes cambiar de un gesto a un botón de accesibilidad\n\n"<annotation id="link">"Configuración"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mueve el botón hacia el borde para ocultarlo temporalmente"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover arriba a la izquierda"</string>
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Consulta mensajes recientes, llamadas perdidas y actualizaciones de estado"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Conversación"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Se detuvo por el modo No interrumpir"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> envió un mensaje: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> envió una imagen"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> actualizó su estado: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problema al leer el medidor de batería"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Presiona para obtener más información"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"No se estableció alarma"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
index 6e6c148..5634f79 100644
--- a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
@@ -33,127 +33,127 @@
<!-- no translation found for tile_states_default:2 (9192445505551219506) -->
<string-array name="tile_states_internet">
<item msgid="5499482407653291407">"No disponible"</item>
- <item msgid="3048856902433862868">"No"</item>
- <item msgid="6877982264300789870">"Sí"</item>
+ <item msgid="3048856902433862868">"Desactivado"</item>
+ <item msgid="6877982264300789870">"Activado"</item>
</string-array>
<string-array name="tile_states_wifi">
<item msgid="8054147400538405410">"No disponible"</item>
- <item msgid="4293012229142257455">"No"</item>
- <item msgid="6221288736127914861">"Sí"</item>
+ <item msgid="4293012229142257455">"Desactivado"</item>
+ <item msgid="6221288736127914861">"Activado"</item>
</string-array>
<string-array name="tile_states_cell">
<item msgid="1235899788959500719">"No disponible"</item>
- <item msgid="2074416252859094119">"No"</item>
- <item msgid="287997784730044767">"Sí"</item>
+ <item msgid="2074416252859094119">"Desactivado"</item>
+ <item msgid="287997784730044767">"Activado"</item>
</string-array>
<string-array name="tile_states_battery">
<item msgid="6311253873330062961">"No disponible"</item>
- <item msgid="7838121007534579872">"No"</item>
- <item msgid="1578872232501319194">"Sí"</item>
+ <item msgid="7838121007534579872">"Desactivado"</item>
+ <item msgid="1578872232501319194">"Activado"</item>
</string-array>
<string-array name="tile_states_dnd">
<item msgid="467587075903158357">"No disponible"</item>
- <item msgid="5376619709702103243">"No"</item>
- <item msgid="4875147066469902392">"Sí"</item>
+ <item msgid="5376619709702103243">"Desactivado"</item>
+ <item msgid="4875147066469902392">"Activado"</item>
</string-array>
<string-array name="tile_states_flashlight">
<item msgid="3465257127433353857">"No disponible"</item>
- <item msgid="5044688398303285224">"No"</item>
- <item msgid="8527389108867454098">"Sí"</item>
+ <item msgid="5044688398303285224">"Desactivado"</item>
+ <item msgid="8527389108867454098">"Activado"</item>
</string-array>
<string-array name="tile_states_rotation">
<item msgid="4578491772376121579">"No disponible"</item>
- <item msgid="5776427577477729185">"No"</item>
- <item msgid="7105052717007227415">"Sí"</item>
+ <item msgid="5776427577477729185">"Desactivado"</item>
+ <item msgid="7105052717007227415">"Activado"</item>
</string-array>
<string-array name="tile_states_bt">
<item msgid="5330252067413512277">"No disponible"</item>
- <item msgid="5315121904534729843">"No"</item>
- <item msgid="503679232285959074">"Sí"</item>
+ <item msgid="5315121904534729843">"Desactivado"</item>
+ <item msgid="503679232285959074">"Activado"</item>
</string-array>
<string-array name="tile_states_airplane">
<item msgid="1985366811411407764">"No disponible"</item>
- <item msgid="4801037224991420996">"No"</item>
- <item msgid="1982293347302546665">"Sí"</item>
+ <item msgid="4801037224991420996">"Desactivado"</item>
+ <item msgid="1982293347302546665">"Activado"</item>
</string-array>
<string-array name="tile_states_location">
<item msgid="3316542218706374405">"No disponible"</item>
- <item msgid="4813655083852587017">"No"</item>
- <item msgid="6744077414775180687">"Sí"</item>
+ <item msgid="4813655083852587017">"Desactivado"</item>
+ <item msgid="6744077414775180687">"Activado"</item>
</string-array>
<string-array name="tile_states_hotspot">
<item msgid="3145597331197351214">"No disponible"</item>
- <item msgid="5715725170633593906">"No"</item>
- <item msgid="2075645297847971154">"Sí"</item>
+ <item msgid="5715725170633593906">"Desactivado"</item>
+ <item msgid="2075645297847971154">"Activado"</item>
</string-array>
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"No disponible"</item>
- <item msgid="9103697205127645916">"No"</item>
- <item msgid="8067744885820618230">"Sí"</item>
+ <item msgid="9103697205127645916">"Desactivado"</item>
+ <item msgid="8067744885820618230">"Activado"</item>
</string-array>
<string-array name="tile_states_saver">
<item msgid="39714521631367660">"No disponible"</item>
- <item msgid="6983679487661600728">"No"</item>
- <item msgid="7520663805910678476">"Sí"</item>
+ <item msgid="6983679487661600728">"Desactivado"</item>
+ <item msgid="7520663805910678476">"Activado"</item>
</string-array>
<string-array name="tile_states_dark">
<item msgid="2762596907080603047">"No disponible"</item>
- <item msgid="400477985171353">"No"</item>
- <item msgid="630890598801118771">"Sí"</item>
+ <item msgid="400477985171353">"Desactivado"</item>
+ <item msgid="630890598801118771">"Activado"</item>
</string-array>
<string-array name="tile_states_work">
<item msgid="389523503690414094">"No disponible"</item>
- <item msgid="8045580926543311193">"No"</item>
- <item msgid="4913460972266982499">"Sí"</item>
+ <item msgid="8045580926543311193">"Desactivado"</item>
+ <item msgid="4913460972266982499">"Activado"</item>
</string-array>
<string-array name="tile_states_cast">
<item msgid="6032026038702435350">"No disponible"</item>
- <item msgid="1488620600954313499">"No"</item>
- <item msgid="588467578853244035">"Sí"</item>
+ <item msgid="1488620600954313499">"Desactivado"</item>
+ <item msgid="588467578853244035">"Activado"</item>
</string-array>
<string-array name="tile_states_night">
<item msgid="7857498964264855466">"No disponible"</item>
- <item msgid="2744885441164350155">"No"</item>
- <item msgid="151121227514952197">"Sí"</item>
+ <item msgid="2744885441164350155">"Desactivada"</item>
+ <item msgid="151121227514952197">"Activada"</item>
</string-array>
<string-array name="tile_states_screenrecord">
<item msgid="1085836626613341403">"No disponible"</item>
- <item msgid="8259411607272330225">"No"</item>
- <item msgid="578444932039713369">"Sí"</item>
+ <item msgid="8259411607272330225">"Desactivado"</item>
+ <item msgid="578444932039713369">"Activado"</item>
</string-array>
<string-array name="tile_states_reverse">
<item msgid="3574611556622963971">"No disponible"</item>
- <item msgid="8707481475312432575">"No"</item>
- <item msgid="8031106212477483874">"Sí"</item>
+ <item msgid="8707481475312432575">"Desactivado"</item>
+ <item msgid="8031106212477483874">"Activado"</item>
</string-array>
<string-array name="tile_states_reduce_brightness">
<item msgid="1839836132729571766">"No disponible"</item>
- <item msgid="4572245614982283078">"No"</item>
- <item msgid="6536448410252185664">"Sí"</item>
+ <item msgid="4572245614982283078">"Desactivado"</item>
+ <item msgid="6536448410252185664">"Activado"</item>
</string-array>
<string-array name="tile_states_cameratoggle">
<item msgid="6680671247180519913">"No disponible"</item>
- <item msgid="4765607635752003190">"No"</item>
- <item msgid="1697460731949649844">"Sí"</item>
+ <item msgid="4765607635752003190">"Desactivado"</item>
+ <item msgid="1697460731949649844">"Activado"</item>
</string-array>
<string-array name="tile_states_mictoggle">
<item msgid="6895831614067195493">"No disponible"</item>
- <item msgid="3296179158646568218">"No"</item>
- <item msgid="8998632451221157987">"Sí"</item>
+ <item msgid="3296179158646568218">"Desactivado"</item>
+ <item msgid="8998632451221157987">"Activado"</item>
</string-array>
<string-array name="tile_states_controls">
<item msgid="8199009425335668294">"No disponible"</item>
- <item msgid="4544919905196727508">"No"</item>
- <item msgid="3422023746567004609">"Sí"</item>
+ <item msgid="4544919905196727508">"Desactivado"</item>
+ <item msgid="3422023746567004609">"Activado"</item>
</string-array>
<string-array name="tile_states_wallet">
<item msgid="4177615438710836341">"No disponible"</item>
- <item msgid="7571394439974244289">"No"</item>
- <item msgid="6866424167599381915">"Sí"</item>
+ <item msgid="7571394439974244289">"Desactivado"</item>
+ <item msgid="6866424167599381915">"Activado"</item>
</string-array>
<string-array name="tile_states_alarm">
<item msgid="4936533380177298776">"No disponible"</item>
- <item msgid="2710157085538036590">"No"</item>
- <item msgid="7809470840976856149">"Sí"</item>
+ <item msgid="2710157085538036590">"Desactivado"</item>
+ <item msgid="7809470840976856149">"Activado"</item>
</string-array>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index c117733..6f23634 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Consulta los mensajes recientes, las llamadas perdidas y los cambios de estado"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Conversación"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Pausado por No molestar"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ha enviado un mensaje: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ha enviado una imagen"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ha cambiado su estado: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"No se ha podido leer el indicador de batería"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Toca la pantalla para consultar más información"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Ninguna alarma puesta"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 682a24f5..d0d33e4 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Vaadake hiljutisi sõnumeid, vastamata kõnesid ja olekuvärskendusi"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Vestlus"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Peatas režiim Mitte segada"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> saatis sõnumi: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> saatis pildi"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> värskendas olekut: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Probleem akumõõdiku lugemisel"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Puudutage lisateabe saamiseks"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Äratust pole"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 57008db..734fb3e 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Ikusi azken mezuak, dei galduak eta egoerari buruzko informazio eguneratua"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Elkarrizketa"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Ez molestatzeko moduak pausatu du"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> erabiltzaileak mezu bat bidali du: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> erabiltzaileak irudi bat bidali du"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> erabiltzaileak egoera eguneratu du: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Arazo bat gertatu da bateria-neurgailua irakurtzean"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Informazio gehiago lortzeko, sakatu hau"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Ez da ezarri alarmarik"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index e85dba2..d974476 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"دیدن بهروزرسانیهای وضعیت، تماسهای بیپاسخ، و پیامهای اخیر"</string>
<string name="people_tile_title" msgid="6589377493334871272">"مکالمه"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"با «مزاحم نشوید» موقتاً متوقف شده است"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> پیامی ارسال کرد: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> تصویری ارسال کرد"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> وضعیتش را بهروزرسانی کرد: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"مشکلی در خواندن میزان باتری وجود دارد"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"برای اطلاعات بیشتر ضربه بزنید"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"هشداری تنظیم نشده است"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index c27418b..98b9953 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Katso viimeaikaiset viestit, vastaamattomat puhelut ja tilapäivitykset"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Keskustelu"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Älä häiritse ‑tilan keskeyttämä"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> lähetti viestin: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> lähetti kuvan"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> on päivittänyt tilansa: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Ongelma akkumittarin lukemisessa"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Saat lisätietoja napauttamalla"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Ei herätyksiä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 6ec3542..e5db4de 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -669,10 +669,8 @@
<string name="wallet_empty_state_label" msgid="7776761245237530394">"Préparez-vous à faire des achats plus rapidement et de façon plus sûre avec votre téléphone"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Tout afficher"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Déverrouiller pour payer"</string>
- <!-- no translation found for wallet_secondary_label_no_card (530725155985223497) -->
- <skip />
- <!-- no translation found for wallet_secondary_label_updating (5726130686114928551) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="530725155985223497">"Ajouter une carte"</string>
+ <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"Mise à jour en cours…"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Déverrouiller pour utiliser"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Un problème est survenu lors de la récupération de vos cartes, veuillez réessayer plus tard"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Paramètres de l\'écran de verrouillage"</string>
@@ -1148,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Affichez les messages récents, les appels manqués et les mises à jour d\'état"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Conversation"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Interrompue par la fonctionnalité Ne pas déranger"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> a envoyé un message : <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> a envoyé une image"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> a mis à jour son état : <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Un problème est survenu lors de la lecture du niveau de charge de la pile"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Touchez pour en savoir plus"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Aucune alarme définie"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 55ab029..6a0fc64 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Voir les messages récents, les appels manqués et les notifications d\'état"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Conversation"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Mise en pause par Ne pas déranger"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> a envoyé un message : <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> a envoyé une image"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> a mis à jour son statut : <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Un problème est survenu au niveau de la lecture de votre outil de mesure de batterie"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Appuyer pour en savoir plus"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Pas d\'alarme définie"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 34f0cdd..94fa675 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Consulta as mensaxes recentes, as chamadas perdidas e as actualizacións dos estados"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Conversa"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Púxose en pausa debido ao modo Non molestar"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> enviou unha mensaxe: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> enviou unha imaxe"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> cambiou de estado: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Produciuse un problema ao ler o medidor da batería"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Toca para obter máis información"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Sen alarmas postas"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 2236d7d..ad3c6a8 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -669,8 +669,7 @@
<string name="wallet_empty_state_label" msgid="7776761245237530394">"તમારા ફોન વડે વધુ ઝડપી તેમજ સુરક્ષિત ખરીદીઓ કરવાની રીત સેટઅપ કરી લો"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"બધું બતાવો"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ચુકવણી કરવા માટે અનલૉક કરો"</string>
- <!-- no translation found for wallet_secondary_label_no_card (530725155985223497) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="530725155985223497">"કોઈ કાર્ડ ઉમેરો"</string>
<string name="wallet_secondary_label_updating" msgid="5726130686114928551">"અપડેટ કરી રહ્યાં છીએ"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ઉપયોગ કરવા માટે અનલૉક કરો"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"તમારા કાર્ડની માહિતી મેળવવામાં સમસ્યા આવી હતી, કૃપા કરીને થોડા સમય પછી ફરી પ્રયાસ કરો"</string>
diff --git a/packages/SystemUI/res/values-gu/tiles_states_strings.xml b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
new file mode 100644
index 0000000..67dfb34
--- /dev/null
+++ b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
+
+<!-- This resources set the default subtitle for tiles. This way, each tile can be translated
+ separately.
+ The indices in the array correspond to the state values in QSTile:
+ * STATE_UNAVAILABLE
+ * STATE_INACTIVE
+ * STATE_ACTIVE
+ This subtitle is shown when the tile is in that particular state but does not set its own
+ subtitle, so some of these may never appear on screen. They should still be translated as if
+ they could appear.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for tile_states_default:0 (4578901299524323311) -->
+ <!-- no translation found for tile_states_default:1 (7086813178962737808) -->
+ <!-- no translation found for tile_states_default:2 (9192445505551219506) -->
+ <string-array name="tile_states_internet">
+ <item msgid="5499482407653291407">"ઉપલબ્ધ નથી"</item>
+ <item msgid="3048856902433862868">"બંધ છે"</item>
+ <item msgid="6877982264300789870">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_wifi">
+ <item msgid="8054147400538405410">"ઉપલબ્ધ નથી"</item>
+ <item msgid="4293012229142257455">"બંધ છે"</item>
+ <item msgid="6221288736127914861">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_cell">
+ <item msgid="1235899788959500719">"ઉપલબ્ધ નથી"</item>
+ <item msgid="2074416252859094119">"બંધ છે"</item>
+ <item msgid="287997784730044767">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_battery">
+ <item msgid="6311253873330062961">"ઉપલબ્ધ નથી"</item>
+ <item msgid="7838121007534579872">"બંધ છે"</item>
+ <item msgid="1578872232501319194">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_dnd">
+ <item msgid="467587075903158357">"ઉપલબ્ધ નથી"</item>
+ <item msgid="5376619709702103243">"બંધ છે"</item>
+ <item msgid="4875147066469902392">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_flashlight">
+ <item msgid="3465257127433353857">"ઉપલબ્ધ નથી"</item>
+ <item msgid="5044688398303285224">"બંધ છે"</item>
+ <item msgid="8527389108867454098">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_rotation">
+ <item msgid="4578491772376121579">"ઉપલબ્ધ નથી"</item>
+ <item msgid="5776427577477729185">"બંધ છે"</item>
+ <item msgid="7105052717007227415">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_bt">
+ <item msgid="5330252067413512277">"ઉપલબ્ધ નથી"</item>
+ <item msgid="5315121904534729843">"બંધ છે"</item>
+ <item msgid="503679232285959074">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_airplane">
+ <item msgid="1985366811411407764">"ઉપલબ્ધ નથી"</item>
+ <item msgid="4801037224991420996">"બંધ છે"</item>
+ <item msgid="1982293347302546665">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_location">
+ <item msgid="3316542218706374405">"ઉપલબ્ધ નથી"</item>
+ <item msgid="4813655083852587017">"બંધ છે"</item>
+ <item msgid="6744077414775180687">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_hotspot">
+ <item msgid="3145597331197351214">"ઉપલબ્ધ નથી"</item>
+ <item msgid="5715725170633593906">"બંધ છે"</item>
+ <item msgid="2075645297847971154">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_inversion">
+ <item msgid="3638187931191394628">"ઉપલબ્ધ નથી"</item>
+ <item msgid="9103697205127645916">"બંધ છે"</item>
+ <item msgid="8067744885820618230">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_saver">
+ <item msgid="39714521631367660">"ઉપલબ્ધ નથી"</item>
+ <item msgid="6983679487661600728">"બંધ છે"</item>
+ <item msgid="7520663805910678476">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_dark">
+ <item msgid="2762596907080603047">"ઉપલબ્ધ નથી"</item>
+ <item msgid="400477985171353">"બંધ છે"</item>
+ <item msgid="630890598801118771">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_work">
+ <item msgid="389523503690414094">"ઉપલબ્ધ નથી"</item>
+ <item msgid="8045580926543311193">"બંધ છે"</item>
+ <item msgid="4913460972266982499">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_cast">
+ <item msgid="6032026038702435350">"ઉપલબ્ધ નથી"</item>
+ <item msgid="1488620600954313499">"બંધ છે"</item>
+ <item msgid="588467578853244035">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_night">
+ <item msgid="7857498964264855466">"ઉપલબ્ધ નથી"</item>
+ <item msgid="2744885441164350155">"બંધ છે"</item>
+ <item msgid="151121227514952197">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_screenrecord">
+ <item msgid="1085836626613341403">"ઉપલબ્ધ નથી"</item>
+ <item msgid="8259411607272330225">"બંધ છે"</item>
+ <item msgid="578444932039713369">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_reverse">
+ <item msgid="3574611556622963971">"ઉપલબ્ધ નથી"</item>
+ <item msgid="8707481475312432575">"બંધ છે"</item>
+ <item msgid="8031106212477483874">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_reduce_brightness">
+ <item msgid="1839836132729571766">"ઉપલબ્ધ નથી"</item>
+ <item msgid="4572245614982283078">"બંધ છે"</item>
+ <item msgid="6536448410252185664">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_cameratoggle">
+ <item msgid="6680671247180519913">"ઉપલબ્ધ નથી"</item>
+ <item msgid="4765607635752003190">"બંધ છે"</item>
+ <item msgid="1697460731949649844">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_mictoggle">
+ <item msgid="6895831614067195493">"ઉપલબ્ધ નથી"</item>
+ <item msgid="3296179158646568218">"બંધ છે"</item>
+ <item msgid="8998632451221157987">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_controls">
+ <item msgid="8199009425335668294">"ઉપલબ્ધ નથી"</item>
+ <item msgid="4544919905196727508">"બંધ છે"</item>
+ <item msgid="3422023746567004609">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_wallet">
+ <item msgid="4177615438710836341">"ઉપલબ્ધ નથી"</item>
+ <item msgid="7571394439974244289">"બંધ છે"</item>
+ <item msgid="6866424167599381915">"ચાલુ છે"</item>
+ </string-array>
+ <string-array name="tile_states_alarm">
+ <item msgid="4936533380177298776">"ઉપલબ્ધ નથી"</item>
+ <item msgid="2710157085538036590">"બંધ છે"</item>
+ <item msgid="7809470840976856149">"ચાલુ છે"</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 4f4c699..ff68699 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"हाल के मैसेज, मिस्ड कॉल, और स्टेटस अपडेट देखें"</string>
<string name="people_tile_title" msgid="6589377493334871272">"बातचीत"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"\'परेशान न करें\' की वजह से सूचनाएं नहीं दिख रहीं"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ने एक मैसेज भेजा है: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ने एक इमेज भेजी है"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ने स्टेटस अपडेट किया है: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"आपके डिवाइस के बैटरी मीटर की रीडिंग लेने में समस्या आ रही है"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"ज़्यादा जानकारी के लिए टैप करें"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"कोई अलार्म सेट नहीं है"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 9933646..a87790d 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -672,7 +672,7 @@
<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_action_button_label_unlock" msgid="8663239748726774487">"Otključajte da biste platili"</string>
- <string name="wallet_secondary_label_no_card" msgid="530725155985223497">"Dodaj karticu"</string>
+ <string name="wallet_secondary_label_no_card" msgid="530725155985223497">"Dodajte karticu"</string>
<string name="wallet_secondary_label_updating" msgid="5726130686114928551">"Ažuriranje"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Otključajte da biste koristili"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Pojavio se problem prilikom dohvaćanja kartica, pokušajte ponovo kasnije"</string>
@@ -1152,11 +1152,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Pogledajte nedavne poruke, propuštene pozive i ažuriranja statusa"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Razgovor"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Pauzirala značajka Ne uznemiravaj"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> šalje poruku: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"Korisnik <xliff:g id="NAME">%1$s</xliff:g> poslao je sliku"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ima ažuriranje statusa: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problem s očitavanjem mjerača baterije"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Dodirnite za više informacija"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nema nijednog alarma"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index a7ee0d8..f954f24 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Megtekintheti a legutóbbi üzeneteket, a nem fogadott hívásokat és az állapotfrissítéseket."</string>
<string name="people_tile_title" msgid="6589377493334871272">"Beszélgetés"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"A Ne zavarjanak mód által szüneteltetve"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> üzenetet küldött: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> képet küldött"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> frissítette állapotát: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Probléma merült fel az akkumulátor-töltésmérő olvasásakor"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Koppintással további információkat érhet el."</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nincs ébresztés"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 144d7f7..fd81c4f 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -670,7 +670,7 @@
<string name="wallet_app_button_label" msgid="7123784239111190992">"Ցույց տալ բոլորը"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Ապակողպել՝ վճարելու համար"</string>
<string name="wallet_secondary_label_no_card" msgid="530725155985223497">"Ավելացնել քարտ"</string>
- <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"Թարմացում"</string>
+ <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"Թարմացվում է"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ապակողպել՝ օգտագործելու համար"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Չհաջողվեց բեռնել քարտերը։ Նորից փորձեք։"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Կողպէկրանի կարգավորումներ"</string>
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Տեսեք վերջին հաղորդագրությունները, բաց թողնված զանգերը և կարգավիճակի մասին թարմացումները"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Զրույց"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Դադարեցվել է «Չանհանգստացնել» գործառույթի կողմից"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> օգտատերը հաղորդագրություն է ուղարկել. «<xliff:g id="NOTIFICATION">%2$s</xliff:g>»"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> օգտատերը պատկեր է ուղարկել"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> օգտատերը նոր կարգավիճակ է հրապարակել. «<xliff:g id="STATUS">%2$s</xliff:g>»"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Մարտկոցի ցուցիչի ցուցմունքը կարդալու հետ կապված խնդիր կա"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Հպեք՝ ավելին իմանալու համար"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Զարթուցիչ դրված չէ"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index dc4f8b2..220656f 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -670,7 +670,7 @@
<string name="wallet_app_button_label" msgid="7123784239111190992">"Tampilkan semua"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Buka kunci untuk membayar"</string>
<string name="wallet_secondary_label_no_card" msgid="530725155985223497">"Tambahkan kartu"</string>
- <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"Mengupdate"</string>
+ <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"Memperbarui"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Buka kunci untuk menggunakan"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Terjadi masalah saat mendapatkan kartu Anda, coba lagi nanti"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Setelan layar kunci"</string>
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Lihat pesan terbaru, panggilan tak terjawab, dan pembaruan status"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Percakapan"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Dijeda oleh fitur Jangan Ganggu"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> mengirim pesan: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> mengirim gambar"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> memposting pembaruan status: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Terjadi masalah saat membaca indikator baterai"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Ketuk untuk informasi selengkapnya"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Alarm tidak disetel"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 66c4268..a0df4b9 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Sjá nýleg skilboð, ósvöruð símtöl og stöðuuppfærslur"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Samtal"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Sett í bið af „Ónáðið ekki“"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> sendi skilaboð: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> sendi mynd"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> er með stöðuuppfærslu: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Vandamál við að lesa stöðu rafhlöðu"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Ýttu til að fá frekari upplýsingar"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Enginn vekjari"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index c5c9289..871a97c 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Visualizza messaggi recenti, chiamate senza risposta e aggiornamenti dello stato"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Conversazione"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"In pausa in base alla modalità Non disturbare"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ha inviato un messaggio: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ha inviato un\'immagine"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ha aggiornato lo stato: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problema durante la lettura dell\'indicatore di livello della batteria"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Tocca per ulteriori informazioni"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nessuna sveglia"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index a23594c..3de805a 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -1158,11 +1158,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"ההודעות האחרונות, שיחות שלא נענו ועדכוני סטטוס"</string>
<string name="people_tile_title" msgid="6589377493334871272">"שיחה"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"ההתראה הושהתה על ידי \'נא לא להפריע\'"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"התקבלה הודעה מ<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> שלח/ה תמונה"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"הסטטוס של <xliff:g id="NAME">%1$s</xliff:g> עודכן: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"בעיה בקריאת מדדי הסוללה"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"יש להקיש כדי להציג מידע נוסף"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"לא הוגדרה התראה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index bd425f8..9e3c616 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"最近のメッセージ、不在着信、最新のステータスが表示されます"</string>
<string name="people_tile_title" msgid="6589377493334871272">"会話"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"サイレント モードにより一時停止"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> さんからのメッセージ: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> さんが画像を送信しました"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> さんの近況: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"バッテリー残量の読み込み中に問題が発生しました"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"タップすると詳細が表示されます"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"アラーム未設定"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index c4545d4..a1a475d 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"ბოლოდროინდელი შეტყობინებების, გამოტოვებული ზარების და სტატუსის განახლებების ნახვა"</string>
<string name="people_tile_title" msgid="6589377493334871272">"მიმოწერა"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"დაპაუზებულია ფუნქციის „არ შემაწუხოთ“ მიერ"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g>-მა გაგზავნა შეტყობინება: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g>-მ(ა) სურათი გამოგზავნა"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g>-მა განაახლა სტატუსი: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"თქვენი ბატარეის მზომის წაკითხვასთან დაკავშირებით პრობლემა დაფიქსირდა"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"შეეხეთ მეტი ინფორმაციისთვის"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"მაღვიძარა არ არის"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 445483d..846dea9 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Соңғы хабарларды, өткізіп алған қоңыраулар мен жаңартылған күйлерді көруге болады."</string>
<string name="people_tile_title" msgid="6589377493334871272">"Әңгіме"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Мазаламау режимі арқылы кідіртілді."</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> хабар жіберді: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> сурет жіберді."</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ағымдағы күйін жаңартты: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Батарея зарядының дерегі алынбай жатыр"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Толығырақ ақпарат алу үшін түртіңіз."</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Оятқыш орнатылмаған."</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 87ecbbe..086ddf3 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"មើលព័ត៌មានថ្មីៗអំពីស្ថានភាព ការខកខានទទួល និងសារថ្មីៗ"</string>
<string name="people_tile_title" msgid="6589377493334871272">"ការសន្ទនា"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"បានផ្អាកដោយមុខងារកុំរំខាន"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> បានផ្ញើសារ៖ <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> បានផ្ញើរូបភាព"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> មានបច្ចុប្បន្នភាពស្ថានភាព៖ <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"មានបញ្ហាក្នុងការអានឧបករណ៍រង្វាស់កម្រិតថ្មរបស់អ្នក"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"ចុចដើម្បីទទួលបានព័ត៌មានបន្ថែម"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"មិនបានកំណត់ម៉ោងរោទ៍ទេ"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 148e137..38fc84e 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -669,8 +669,7 @@
<string name="wallet_empty_state_label" msgid="7776761245237530394">"ನಿಮ್ಮ ಫೋನ್ ಮೂಲಕ ವೇಗವಾದ, ಹೆಚ್ಚು ಸುರಕ್ಷಿತ ಖರೀದಿಗಳನ್ನು ಮಾಡಲು ಸೆಟಪ್ ಮಾಡಿಕೊಳ್ಳಿ"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"ಎಲ್ಲವನ್ನೂ ತೋರಿಸಿ"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ಪಾವತಿಸಲು ಅನ್ಲಾಕ್ ಮಾಡಿ"</string>
- <!-- no translation found for wallet_secondary_label_no_card (530725155985223497) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="530725155985223497">"ಕಾರ್ಡ್ ಅನ್ನು ಸೇರಿಸಿ"</string>
<string name="wallet_secondary_label_updating" msgid="5726130686114928551">"ಅಪ್ಡೇಟ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ಬಳಸಲು ಅನ್ಲಾಕ್ ಮಾಡಿ"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"ನಿಮ್ಮ ಕಾರ್ಡ್ಗಳನ್ನು ಪಡೆಯುವಾಗ ಸಮಸ್ಯೆ ಉಂಟಾಗಿದೆ, ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"</string>
@@ -998,7 +997,7 @@
<string name="slice_permission_deny" msgid="6870256451658176895">"ನಿರಾಕರಿಸಿ"</string>
<string name="auto_saver_title" msgid="6873691178754086596">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಅನ್ನು ನಿಗದಿಗೊಳಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="auto_saver_text" msgid="3214960308353838764">"ಬ್ಯಾಟರಿ ಖಾಲಿಯಾಗುವ ಸಾಧ್ಯತೆ ಇದ್ದಾಗ ಆನ್ ಮಾಡಿ"</string>
- <string name="no_auto_saver_action" msgid="7467924389609773835">"ಬೇಡ ಧನ್ಯವಾದಗಳು"</string>
+ <string name="no_auto_saver_action" msgid="7467924389609773835">"ಬೇಡ"</string>
<string name="auto_saver_enabled_title" msgid="4294726198280286333">"ಬ್ಯಾಟರಿ ಸೇವರ್ ನಿಗದಿಯನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="auto_saver_enabled_text" msgid="7889491183116752719">"ಬ್ಯಾಟರಿ <xliff:g id="PERCENTAGE">%d</xliff:g>%% ಗಿಂತ ಕಡಿಮೆ ಆದಾಗ ಬ್ಯಾಟರಿ ಸೇವರ್ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆನ್ ಆಗುತ್ತದೆ."</string>
<string name="open_saver_setting_action" msgid="2111461909782935190">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
@@ -1147,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"ಇತ್ತೀಚಿನ ಸಂದೇಶಗಳು, ಮಿಸ್ಡ್ ಕಾಲ್ಗಳು ಮತ್ತು ಸ್ಥಿತಿ ಅಪ್ಡೇಟ್ಗಳು"</string>
<string name="people_tile_title" msgid="6589377493334871272">"ಸಂಭಾಷಣೆ"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"\'ಅಡಚಣೆ ಮಾಡಬೇಡಿ\' ನಿಂದ ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ಅವರು ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಿದ್ದಾರೆ: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ಅವರು ಚಿತ್ರವನ್ನು ಕಳುಹಿಸಿದ್ದಾರೆ"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ಅವರು ಸ್ಥಿತಿಯ ಅಪ್ಡೇಟ್ ಹೊಂದಿದ್ದಾರೆ: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"ನಿಮ್ಮ ಬ್ಯಾಟರಿ ಮೀಟರ್ ಓದುವಾಗ ಸಮಸ್ಯೆ ಎದುರಾಗಿದೆ"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"ಇನ್ನಷ್ಟು ಮಾಹಿತಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"ಅಲಾರಾಂ ಸೆಟ್ ಆಗಿಲ್ಲ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 1d47072..2d07d94 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -1034,9 +1034,9 @@
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"전체 화면 확대"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"화면 일부 확대"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"전환"</string>
- <string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"접근성 동작이 접근성 버튼으로 대체되었습니다\n\n"<annotation id="link">"설정 보기"</annotation></string>
+ <string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"접근성 동작이 접근성 버튼으로 대체되었습니다.\n\n"<annotation id="link">"설정 보기"</annotation></string>
<string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"접근성 동작을 버튼으로 전환할 수 있습니다.\n\n"<annotation id="link">"설정"</annotation></string>
- <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"버튼을 가장자리로 옮겨서 일시적으로 숨기세요"</string>
+ <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"버튼을 가장자리로 옮겨서 일시적으로 숨기세요."</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"왼쪽 상단으로 이동"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"오른쪽 상단으로 이동"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"왼쪽 하단으로 이동"</string>
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"최근 메시지, 부재중 전화, 상태 업데이트 보기"</string>
<string name="people_tile_title" msgid="6589377493334871272">"대화"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"방해 금지 모드로 인해 일시중지됨"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g>님이 메시지를 보냈습니다: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g>님이 이미지를 보냈습니다."</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g>님의 상태가 업데이트되었습니다: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"배터리 수준을 읽는 중에 문제가 발생함"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"탭하여 자세한 정보를 확인하세요."</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"설정된 알람 없음"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index c0c42c3..ad244f1 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Акыркы билдирүүлөрдү, жооп берилбеген чалууларды жана статустардын жаңырганын көрөсүз"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Сүйлөшүү"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"\"Тынчымды алба\" режими тындырды"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> билдирүү жөнөттү: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> сүрөт жөнөттү"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> жаңы абалы тууралуу жарыялады: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Батареяңыздын кубаты аныкталбай жатат"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Кеңири маалымат алуу үчүн таптап коюңуз"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Ойготкуч коюлган жок"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 3275d28..f47b8e8 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"ເບິ່ງຂໍ້ຄວາມຫຼ້າສຸດ, ສາຍບໍ່ໄດ້ຮັບ ແລະ ອັບເດດສະຖານະ"</string>
<string name="people_tile_title" msgid="6589377493334871272">"ການສົນທະນາ"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"ຢຸດຊົ່ວຄາວແລ້ວໂດຍໂໝດຫ້າມລົບກວນ"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ສົ່ງຂໍ້ຄວາມ: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ສົ່ງຮູບພາບແລ້ວ"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ອັບເດດສະຖານະ: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"ເກີດບັນຫາໃນການອ່ານຕົວວັດແທກແບັດເຕີຣີຂອງທ່ານ"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"ແຕະເພື່ອເບິ່ງຂໍ້ມູນເພີ່ມເຕີມ"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"ບໍ່ໄດ້ຕັ້ງໂມງປຸກ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 1df1f8a..e12afb55 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -1158,11 +1158,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Peržiūrėkite naujausius pranešimus, praleistus skambučius ir būsenos atnaujinimus"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Pokalbis"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Pristabdyta dėl netrukdymo režimo"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> išsiuntė pranešimą: „<xliff:g id="NOTIFICATION">%2$s</xliff:g>“"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> išsiuntė vaizdą"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> atnaujino būseną: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Nuskaitant akumuliatoriaus skaitiklį iškilo problema"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Palieskite, kad sužinotumėte daugiau informacijos"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nenustatyta signalų"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index bb875f3..1d0b0ff 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -1152,11 +1152,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Skatiet jaunākos ziņojumus, neatbildētos zvanus un statusa atjauninājumus."</string>
<string name="people_tile_title" msgid="6589377493334871272">"Saruna"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Rādīšana pārtraukta režīma Netraucēt dēļ"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> nosūtīja ziņojumu: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> nosūtīja attēlu"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> atjaunināja statusu: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Nevar iegūt informāciju par akumulatora uzlādes līmeni."</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Pieskarieties, lai iegūtu plašāku informāciju."</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nav iestatīts signāls"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 3bfc433..39db339 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Видете ги неодамнешните пораки, пропуштени повици и промени на статусот"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Разговор"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Паузирано од „Не вознемирувај“"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> испрати порака: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> испрати слика"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> има ажурирање на статусот: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Проблем при читањето на мерачот на батеријата"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Допрете за повеќе информации"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Не е поставен аларм"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index a18780b..d72466a 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"അടുത്തിടെയുള്ള സന്ദേശങ്ങൾ, മിസ്ഡ് കോൾ, സ്റ്റാറ്റസ് അപ്ഡേറ്റുകൾ എന്നിവ കാണൂ"</string>
<string name="people_tile_title" msgid="6589377493334871272">"സംഭാഷണം"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"\'ശല്യപ്പെടുത്തരുത്\' ഓണായതിനാൽ തൽക്കാലം നിർത്തി"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ഒരു സന്ദേശം അയച്ചു: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g>, ഒരു ചിത്രം അയച്ചു"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> എന്നയാൾ സ്റ്റാറ്റസ് അപ്ഡേറ്റ് ചെയ്തു: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"നിങ്ങളുടെ ബാറ്ററി മീറ്റർ വായിക്കുന്നതിൽ പ്രശ്നമുണ്ട്"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"കൂടുതൽ വിവരങ്ങൾക്ക് ടാപ്പ് ചെയ്യുക"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"അലാറം സജ്ജീകരിച്ചിട്ടില്ല"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 7e8d0cb..9fe4d0a 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Саяхны мессеж, аваагүй дуудлага болон төлөвийн шинэчлэлтийг харах"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Харилцан яриа"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Бүү саад бол горимоор түр зогсоосон"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> мессеж илгээсэн: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> зураг илгээсэн"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> төлөвийн шинэчлэлт хийсэн байна: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Таны батарей хэмжигчийг уншихад асуудал гарлаа"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Нэмэлт мэдээлэл авахын тулд товшино уу"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Сэрүүлэг тавиагүй"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 9295805..4091375 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Lihat mesej terbaharu, panggilan terlepas dan kemaskinian status"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Perbualan"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Dijeda oleh Jangan Ganggu"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> menghantar mesej: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> menghantar imej"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> mempunyai kemaskinian status: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Masalah membaca meter bateri anda"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Ketik untuk mendapatkan maklumat lanjut"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Tiada penggera"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index c6a64d5..51c800f 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"မကြာသေးမီက မက်ဆေ့ဂျ်၊ လွတ်သွားသောခေါ်ဆိုမှုနှင့် အခြေအနေအပ်ဒိတ်များကို ကြည့်နိုင်သည်"</string>
<string name="people_tile_title" msgid="6589377493334871272">"စကားဝိုင်း"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"‘မနှောင့်ယှက်ရ’ ဖြင့် ခဏရပ်ထားသည်"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> က မက်ဆေ့ဂျ်ပို့လိုက်သည်- <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> က ပုံပို့လိုက်သည်"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> က အခြေအနေ အပ်ဒိတ်လုပ်လိုက်သည်- <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"သင်၏ ဘက်ထရီမီတာကို ဖတ်ရာတွင် ပြဿနာရှိနေသည်"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"နောက်ထပ်အချက်အလက်များအတွက် တို့ပါ"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"နှိုးစက်ပေးမထားပါ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 55db4a9..69d636d 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Se nylige meldinger, tapte anrop og statusoppdateringer"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Samtale"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Satt på pause av «Ikke forstyrr»"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> har sendt en melding: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> har sendt et bilde"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> har en statusoppdatering: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Kunne ikke lese batterimåleren"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Trykk for å få mer informasjon"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Ingen alarm angitt"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 5b556c6..8bb7d86 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"हालसालैका म्यासेज, मिस कल र स्ट्याटस अपडेट हेर्नुहोस्"</string>
<string name="people_tile_title" msgid="6589377493334871272">"वार्तालाप"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"\'बाधा नपुऱ्याउनुहोस्\' ले पज गरेको छ"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ले एउटा म्यासेज पठाउनुभएको छ: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ले एउटा फोटो पठाउनुभयो"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ले स्ट्याटस अपडेट गर्नुभएको छ: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"डिभाइसको ब्याट्रीको मिटर रिडिङ क्रममा समस्या भयो"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"थप जानकारी प्राप्त गर्न ट्याप गर्नुहोस्"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"अलार्म राखिएको छैन"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 3626c8e..c9e869d 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Bekijk recente berichten, gemiste gesprekken en statusupdates"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Gesprek"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Onderbroken door Niet storen"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> heeft een bericht gestuurd: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> heeft een afbeelding gestuurd"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> heeft een statusupdate: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Probleem bij het lezen van je batterijmeter"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Tik hier voor meer informatie"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Geen wekker gezet"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 8b1fb55..a209581 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"ବର୍ତ୍ତମାନର ମେସେଜ୍, ମିସ୍ଡ କଲ୍ ଏବଂ ସ୍ଥିତି ଅପଡେଟଗୁଡ଼ିକୁ ଦେଖନ୍ତୁ"</string>
<string name="people_tile_title" msgid="6589377493334871272">"ବାର୍ତ୍ତାଳାପ"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" ଦ୍ୱାରା ବିରତ କରାଯାଇଛି"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ଏକ ମେସେଜ୍ ପଠାଇଛନ୍ତି: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ଏକ ଛବି ପଠାଇଛନ୍ତି"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ଏକ ସ୍ଥିତି ଅପଡେଟ୍ କରିଛନ୍ତି: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"ଆପଣଙ୍କ ବ୍ୟାଟେରୀ ମିଟର୍ ପଢ଼ିବାରେ ସମସ୍ୟା ହେଉଛି"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"ଅଧିକ ସୂଚନା ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"ଆଲାରାମ ସେଟ୍ ହୋଇନାହିଁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 699fd8f..49b1f9a 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -669,9 +669,8 @@
<string name="wallet_empty_state_label" msgid="7776761245237530394">"ਆਪਣੇ ਫ਼ੋਨ ਨਾਲ ਜ਼ਿਆਦਾ ਤੇਜ਼ ਅਤੇ ਜ਼ਿਆਦਾ ਸੁਰੱਖਿਅਤ ਖਰੀਦਾਂ ਕਰਨ ਲਈ ਸੈੱਟਅੱਪ ਕਰੋ"</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"ਸਭ ਦਿਖਾਓ"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"ਭੁਗਤਾਨ ਕਰਨ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string>
- <!-- no translation found for wallet_secondary_label_no_card (530725155985223497) -->
- <skip />
- <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"ਅੱਪਡੇਟ ਹੋ ਰਿਹਾ ਹੈ"</string>
+ <string name="wallet_secondary_label_no_card" msgid="530725155985223497">"ਕੋਈ ਕਾਰਡ ਸ਼ਾਮਲ ਕਰੋ"</string>
+ <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"ਅੱਪਡੇਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ਵਰਤਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"ਤੁਹਾਡੇ ਕਾਰਡ ਪ੍ਰਾਪਤ ਕਰਨ ਵਿੱਚ ਕੋਈ ਸਮੱਸਿਆ ਆਈ, ਕਿਰਪਾ ਕਰਕੇ ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ਲਾਕ ਸਕ੍ਰੀਨ ਸੈਟਿੰਗਾਂ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 0123d1b..fb433c5 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -1017,8 +1017,8 @@
<string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacje używają: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
<string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
<string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string>
- <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Używa tego aplikacja <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
- <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Ostatnio używała tego aplikacja <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
+ <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Używane przez aplikację <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
+ <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Ostatnio używane przez aplikację <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(praca)"</string>
<string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Rozmowa telefoniczna"</string>
<string name="ongoing_privacy_dialog_attribution_text" msgid="4738795925380373994">"(przez: <xliff:g id="APPLICATION_NAME_S_">%s</xliff:g>)"</string>
@@ -1158,11 +1158,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Zobacz ostatnie wiadomości, nieodebrane połączenia i stany"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Rozmowa"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Wstrzymane przez tryb Nie przeszkadzać"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> wysyła wiadomość: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> wysyła zdjęcie"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ma nowy stan: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problem z odczytaniem pomiaru wykorzystania baterii"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Kliknij, aby uzyskać więcej informacji"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nie ustawiono alarmu"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index e3bd8c7..e33c106 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Veja mensagens recentes, chamadas perdidas e atualizações de status"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Conversa"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Pausado pelo Não perturbe"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> enviou uma mensagem: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> enviou uma imagem"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> atualizou o status: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problema para ler seu medidor de bateria"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Toque para mais informações"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nenhum alarme definido"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index b560c95..2965cb7 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Veja mensagens recentes, chamadas não atendidas e atualizações de estado"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Conversa"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Colocado em pausa pelo modo Não incomodar"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> enviou uma mensagem: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> enviou uma imagem"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> tem uma atualização de estado: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Ocorreu um problema ao ler o medidor da bateria"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Toque para obter mais informações"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nenhum alarme defin."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index e3bd8c7..e33c106 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Veja mensagens recentes, chamadas perdidas e atualizações de status"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Conversa"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Pausado pelo Não perturbe"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> enviou uma mensagem: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> enviou uma imagem"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> atualizou o status: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problema para ler seu medidor de bateria"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Toque para mais informações"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nenhum alarme definido"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 622d330..90c76ad 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -1152,11 +1152,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Vedeți mesaje recente, apeluri pierdute și actualizări de stare"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Conversație"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Întrerupt de Nu deranja"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> a trimis un mesaj: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> a trimis o imagine"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> are o nouă stare: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problemă la citirea măsurării bateriei"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Atingeți pentru mai multe informații"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nicio alarmă setată"</string>
diff --git a/packages/SystemUI/res/values-ro/tiles_states_strings.xml b/packages/SystemUI/res/values-ro/tiles_states_strings.xml
index 3201c3e..3f56424 100644
--- a/packages/SystemUI/res/values-ro/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ro/tiles_states_strings.xml
@@ -32,14 +32,14 @@
<!-- no translation found for tile_states_default:1 (7086813178962737808) -->
<!-- no translation found for tile_states_default:2 (9192445505551219506) -->
<string-array name="tile_states_internet">
- <item msgid="5499482407653291407">"Indisponibilă"</item>
- <item msgid="3048856902433862868">"Dezactivată"</item>
- <item msgid="6877982264300789870">"Activată"</item>
+ <item msgid="5499482407653291407">"Indisponibil"</item>
+ <item msgid="3048856902433862868">"Dezactivat"</item>
+ <item msgid="6877982264300789870">"Activat"</item>
</string-array>
<string-array name="tile_states_wifi">
- <item msgid="8054147400538405410">"Indisponibilă"</item>
- <item msgid="4293012229142257455">"Dezactivată"</item>
- <item msgid="6221288736127914861">"Activată"</item>
+ <item msgid="8054147400538405410">"Indisponibil"</item>
+ <item msgid="4293012229142257455">"Dezactivat"</item>
+ <item msgid="6221288736127914861">"Activat"</item>
</string-array>
<string-array name="tile_states_cell">
<item msgid="1235899788959500719">"Indisponibilă"</item>
@@ -67,14 +67,14 @@
<item msgid="7105052717007227415">"Activată"</item>
</string-array>
<string-array name="tile_states_bt">
- <item msgid="5330252067413512277">"Indisponibilă"</item>
- <item msgid="5315121904534729843">"Dezactivată"</item>
- <item msgid="503679232285959074">"Activată"</item>
+ <item msgid="5330252067413512277">"Indisponibil"</item>
+ <item msgid="5315121904534729843">"Dezactivat"</item>
+ <item msgid="503679232285959074">"Activat"</item>
</string-array>
<string-array name="tile_states_airplane">
- <item msgid="1985366811411407764">"Indisponibilă"</item>
- <item msgid="4801037224991420996">"Dezactivată"</item>
- <item msgid="1982293347302546665">"Activată"</item>
+ <item msgid="1985366811411407764">"Indisponibil"</item>
+ <item msgid="4801037224991420996">"Dezactivat"</item>
+ <item msgid="1982293347302546665">"Activat"</item>
</string-array>
<string-array name="tile_states_location">
<item msgid="3316542218706374405">"Indisponibilă"</item>
@@ -82,9 +82,9 @@
<item msgid="6744077414775180687">"Activată"</item>
</string-array>
<string-array name="tile_states_hotspot">
- <item msgid="3145597331197351214">"Indisponibilă"</item>
- <item msgid="5715725170633593906">"Dezactivată"</item>
- <item msgid="2075645297847971154">"Activată"</item>
+ <item msgid="3145597331197351214">"Indisponibil"</item>
+ <item msgid="5715725170633593906">"Dezactivat"</item>
+ <item msgid="2075645297847971154">"Activat"</item>
</string-array>
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Indisponibilă"</item>
@@ -97,14 +97,14 @@
<item msgid="7520663805910678476">"Activată"</item>
</string-array>
<string-array name="tile_states_dark">
- <item msgid="2762596907080603047">"Indisponibilă"</item>
- <item msgid="400477985171353">"Dezactivată"</item>
- <item msgid="630890598801118771">"Activată"</item>
+ <item msgid="2762596907080603047">"Indisponibil"</item>
+ <item msgid="400477985171353">"Dezactivat"</item>
+ <item msgid="630890598801118771">"Activat"</item>
</string-array>
<string-array name="tile_states_work">
- <item msgid="389523503690414094">"Indisponibilă"</item>
- <item msgid="8045580926543311193">"Dezactivată"</item>
- <item msgid="4913460972266982499">"Activată"</item>
+ <item msgid="389523503690414094">"Indisponibil"</item>
+ <item msgid="8045580926543311193">"Dezactivat"</item>
+ <item msgid="4913460972266982499">"Activat"</item>
</string-array>
<string-array name="tile_states_cast">
<item msgid="6032026038702435350">"Indisponibilă"</item>
@@ -127,9 +127,9 @@
<item msgid="8031106212477483874">"Activată"</item>
</string-array>
<string-array name="tile_states_reduce_brightness">
- <item msgid="1839836132729571766">"Indisponibilă"</item>
- <item msgid="4572245614982283078">"Dezactivată"</item>
- <item msgid="6536448410252185664">"Activată"</item>
+ <item msgid="1839836132729571766">"Indisponibil"</item>
+ <item msgid="4572245614982283078">"Dezactivat"</item>
+ <item msgid="6536448410252185664">"Activat"</item>
</string-array>
<string-array name="tile_states_cameratoggle">
<item msgid="6680671247180519913">"Indisponibilă"</item>
@@ -147,9 +147,9 @@
<item msgid="3422023746567004609">"Activată"</item>
</string-array>
<string-array name="tile_states_wallet">
- <item msgid="4177615438710836341">"Indisponibilă"</item>
- <item msgid="7571394439974244289">"Dezactivată"</item>
- <item msgid="6866424167599381915">"Activată"</item>
+ <item msgid="4177615438710836341">"Indisponibil"</item>
+ <item msgid="7571394439974244289">"Dezactivat"</item>
+ <item msgid="6866424167599381915">"Activat"</item>
</string-array>
<string-array name="tile_states_alarm">
<item msgid="4936533380177298776">"Indisponibilă"</item>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 1a962de..7f27437 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -676,7 +676,7 @@
<string name="wallet_app_button_label" msgid="7123784239111190992">"Показать все"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Разблокировать для оплаты"</string>
<string name="wallet_secondary_label_no_card" msgid="530725155985223497">"Добавьте карту"</string>
- <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"Обновление"</string>
+ <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"Обновление…"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Разблокировать для использования"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Не удалось получить информацию о картах. Повторите попытку позже."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Настройки заблокированного экрана"</string>
@@ -1158,11 +1158,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Будьте в курсе последних сообщений, пропущенных вызовов и обновлений статуса."</string>
<string name="people_tile_title" msgid="6589377493334871272">"Чат"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Приостановлено в режиме \"Не беспокоить\""</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"Пользователь <xliff:g id="NAME">%1$s</xliff:g> отправил сообщение: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"Пользователь <xliff:g id="NAME">%1$s</xliff:g> отправил изображение"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"Пользователь <xliff:g id="NAME">%1$s</xliff:g> обновил статус: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Не удается получить данные об уровне заряда батареи"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Нажмите, чтобы узнать больше."</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Будильников нет"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index a7e5839..79eb6ba 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"මෑත පණිවිඩ, මඟ හැරුණු ඇමතුම් සහ තත්ත්ව යාවත්කාලීන කිරීම් බලන්න"</string>
<string name="people_tile_title" msgid="6589377493334871272">"සංවාදය"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"බාධා නොකිරීම මගින් විරාම කර ඇත"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> පණිවිඩයක් එවා ඇත: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> රූපයක් යවන ලදී"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> හට තත්ත්ව යාවත්කාලීනයක් ඇත: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"ඔබගේ බැටරි මනුව කියවීමේ දෝෂයකි"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"තවත් තොරතුරු සඳහා තට්ටු කරන්න"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"එලාම සකසා නැත"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index ddf054a..0158d27 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -1158,11 +1158,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Pozrite si nedávne správy, zmeškané hovory a aktualizácie stavu"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Konverzácia"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Pozastavené režimom bez vyrušení"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> poslal(a) správu: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> poslal(a) obrázok"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> má aktualizáciu statusu: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Pri čítaní meradla batérie sa vyskytol problém"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Klepnutím si zobrazíte ďalšie informácie"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Žiadny budík"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 69e0cf6..1af9e02 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -1158,11 +1158,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Ogled nedavnih sporočil, neodgovorjenih klicev in posodobitev stanj"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Pogovor"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"To je začasno zaustavil način »ne moti«."</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"Oseba <xliff:g id="NAME">%1$s</xliff:g> je poslala sporočilo: <xliff:g id="NOTIFICATION">%2$s</xliff:g>."</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"Oseba <xliff:g id="NAME">%1$s</xliff:g> je poslala sliko."</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"Oseba <xliff:g id="NAME">%1$s</xliff:g> je posodobila stanje: <xliff:g id="STATUS">%2$s</xliff:g>."</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Težava z branjem indikatorja stanja napolnjenosti baterije"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Dotaknite se za več informacij"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Ni nastavljenih alarmov"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index feb5c87..78fbc1a 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -669,10 +669,8 @@
<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_action_button_label_unlock" msgid="8663239748726774487">"Shkyçe për të paguar"</string>
- <!-- no translation found for wallet_secondary_label_no_card (530725155985223497) -->
- <skip />
- <!-- no translation found for wallet_secondary_label_updating (5726130686114928551) -->
- <skip />
+ <string name="wallet_secondary_label_no_card" msgid="530725155985223497">"Shto një kartë"</string>
+ <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"Po përditësohet"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Shkyçe për ta përdorur"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Pati një problem me marrjen e kartave të tua. Provo përsëri më vonë"</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Cilësimet e ekranit të kyçjes"</string>
@@ -1148,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Shiko mesazhet e fundit, telefonatat e humbura dhe përditësimet e statusit"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Biseda"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Vendosur në pauzë nga \"Mos shqetëso\""</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> dërgoi një mesazh: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> dërgoi një imazh"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ka një përditësim të statusit: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problem me leximin e matësit të baterisë"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Trokit për më shumë informacione"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Nuk është caktuar asnjë alarm"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 1b6f08d..e9fbb78 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -1152,11 +1152,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Погледајте недавне поруке, пропуштене позиве и ажурирања статуса"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Конверзација"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Паузирано режимом Не узнемиравај"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> је послао/ла поруку: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> шаље слику"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> има ажурирање статуса: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Проблем са очитавањем мерача батерије"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Додирните за више информација"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Аларм није подешен"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 991d42f..bcead0b 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Se de senaste meddelandena, missade samtal och statusuppdateringar"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Konversation"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Pausad av Stör ej"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> skickade ett meddelande: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> skickade en bild"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> har gjort en statusuppdatering: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Batteriindikatorn visas inte"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Tryck för mer information"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Inget inställt alarm"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 8be37c23..8fa401a 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Angalia ujumbe wa hivi majuzi, simu ambazo hukujibu na taarifa za hali"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Mazungumzo"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Imesimamishwa na kipengele cha Usinisumbue"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ametuma ujumbe: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ametuma picha"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ana taarifa kuhusu hali: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Tatizo la kusoma mita ya betri yako"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Gusa ili upate maelezo zaidi"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Hujaweka kengele"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 9c8ddca..183b559 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"சமீபத்திய மெசேஜ்களையும் தவறிய அழைப்புகளையும் ஸ்டேட்டஸ் அப்டேட்களையும் பார்க்கலாம்"</string>
<string name="people_tile_title" msgid="6589377493334871272">"உரையாடல்"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"தொந்தரவு செய்ய வேண்டாம் அம்சத்தால் இடைநிறுத்தப்பட்டது"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ஒரு மெசேஜ் அனுப்பியுள்ளார்: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ஒரு படம் அனுப்பியுள்ளார்"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> புதிய ஸ்டேட்டஸ் வைத்துள்ளார்: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"பேட்டரி அளவை அறிவதில் சிக்கல்"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"மேலும் தகவல்களுக்கு தட்டவும்"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"அலாரம் எதுவுமில்லை"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index d4375a5..778ed64 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"ఇటీవలి మెసేజ్లు, మిస్డ్ కాల్లు, అలాగే స్టేటస్ అప్డేట్లను చూడండి"</string>
<string name="people_tile_title" msgid="6589377493334871272">"సంభాషణ"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"అంతరాయం కలిగించవద్దు ద్వారా పాజ్ చేయబడింది"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> మెసేజ్ను పంపారు: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ఇమేజ్ను పంపారు"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g>, స్టేటస్ను గురించిన అప్డేట్ను కలిగి ఉన్నారు: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"మీ బ్యాటరీ మీటర్ను చదవడంలో సమస్య"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"మరింత సమాచారం కోసం ట్యాప్ చేయండి"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"అలారం సెట్ చేయలేదు"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 8b28b0e..6ecb2b4 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -1007,8 +1007,8 @@
<string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"หลายแอปพลิเคชันใช้<xliff:g id="TYPES_LIST">%s</xliff:g>ของคุณอยู่"</string>
<string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
<string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" และ "</string>
- <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"ใช้อยู่โดย <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
- <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"ใช้ล่าสุดโดย <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
+ <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"ใช้อยู่โดย<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
+ <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"ใช้ล่าสุดโดย<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
<string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(ที่ทำงาน)"</string>
<string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"การโทร"</string>
<string name="ongoing_privacy_dialog_attribution_text" msgid="4738795925380373994">"(ผ่านทาง <xliff:g id="APPLICATION_NAME_S_">%s</xliff:g>)"</string>
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"ดูข้อความล่าสุด สายที่ไม่ได้รับ และการอัปเดตสถานะ"</string>
<string name="people_tile_title" msgid="6589377493334871272">"การสนทนา"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"หยุดชั่วคราวโดยฟีเจอร์ห้ามรบกวน"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> ส่งข้อความ: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> ส่งรูปภาพ"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> มีการอัปเดตสถานะ: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"พบปัญหาในการอ่านเครื่องวัดแบตเตอรี่"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"แตะดูข้อมูลเพิ่มเติม"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"ไม่มีการตั้งปลุก"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 0965816..cf38fa20 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Tingnan ang mga kamakailang mensahe, hindi nasagot na tawag, at update sa status"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Pag-uusap"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Na-pause ng Huwag Istorbohin"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"Nagpadala si <xliff:g id="NAME">%1$s</xliff:g> ng mensahe: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"Nagpadala si <xliff:g id="NAME">%1$s</xliff:g> ng larawan"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"May update sa status si <xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Nagkaproblema sa pagbabasa ng iyong battery meter"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"I-tap para sa higit pang impormasyon"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Walang alarm"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index ea58c4e..7308785 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Yeni mesajları, cevapsız aramaları ve durum güncellemelerini görün"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Görüşme"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Rahatsız Etmeyin özelliği tarafından duraklatıldı"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> bir mesaj gönderdi: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> bir resim gönderdi"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g>, durumunu güncelledi: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Pil ölçeriniz okunurken sorun oluştu"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Daha fazla bilgi için dokunun"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Alarm ayarlanmadı"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 663e960..bc62ea0 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -676,7 +676,7 @@
<string name="wallet_app_button_label" msgid="7123784239111190992">"Показати все"</string>
<string name="wallet_action_button_label_unlock" msgid="8663239748726774487">"Розблокувати, щоб сплатити"</string>
<string name="wallet_secondary_label_no_card" msgid="530725155985223497">"Додати картку"</string>
- <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"Триває оновлення"</string>
+ <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"Оновлення"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Розблокувати, щоб використовувати"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Не вдалось отримати ваші картки. Повторіть спробу пізніше."</string>
<string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Параметри блокування екрана"</string>
@@ -1158,11 +1158,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Переглядайте останні повідомлення, пропущені виклики й оновлення статусу"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Розмова"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Призупинено функцією \"Не турбувати\""</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> надсилає повідомлення: \"<xliff:g id="NOTIFICATION">%2$s</xliff:g>\""</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> надсилає зображення"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> публікує новий статус: \"<xliff:g id="STATUS">%2$s</xliff:g>\""</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Не вдалось отримати дані лічильника акумулятора"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Натисніть, щоб дізнатися більше"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Немає будильників"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 0612014..4baffd2 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"حالیہ پیغامات، چھوٹی ہوئی کالز اور اسٹیٹس اپ ڈیٹس دیکھیں"</string>
<string name="people_tile_title" msgid="6589377493334871272">"گفتگو"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"\'ڈسٹرب نہ کریں\' کے ذریعے موقوف کیا گیا"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> نے ایک پیغام بھیجا: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> نے ایک تصویر بھیجی"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> نے اسٹیٹس کو اپ ڈیٹ کر دیا ہے: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"آپ کے بیٹری میٹر کو پڑھنے میں دشواری"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"مزید معلومات کے لیے تھپتھپائیں"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"کوئی الارم سیٹ نہیں ہے"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index ca09818..c544256 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Oxirgi xabarlar, javobsiz chaqiruvlar va holat yangilanishlari"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Suhbat"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Bezovta qilinmasin rejimi pauza qildi"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> xabar yubordi: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> rasm yubordi"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> ahvolini yangiladi: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Batareya quvvati aniqlanmadi"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Batafsil axborot olish uchun bosing"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Signal sozlanmagan"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 3cf2b55..46ebcb3 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Xem các tin nhắn, cuộc gọi nhỡ và thông tin cập nhật trạng thái gần đây"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Cuộc trò chuyện"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Đã tạm dừng do chế độ Không làm phiền"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> đã gửi một tin nhắn: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> đã gửi một hình ảnh"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> đã cập nhật trạng thái: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Đã xảy ra vấn đề khi đọc dung lượng pin của bạn"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Nhấn để biết thêm thông tin"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Chưa đặt chuông báo"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 7cb429b..f3fb2cf 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"查看近期的消息、未接电话和状态更新"</string>
<string name="people_tile_title" msgid="6589377493334871272">"对话"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"勿扰模式已暂停通知"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g>发送了一条消息:<xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g>发送了一张图片"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g>更新了状态:<xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"读取电池计量器时出现问题"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"点按即可了解详情"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"未设置闹钟"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 0e773a9..641c9b7 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"查看最近的訊息、未接來電和狀態更新"</string>
<string name="people_tile_title" msgid="6589377493334871272">"對話"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"「請勿騷擾」已暫停通知"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g>傳送了訊息:<xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g>傳送了圖片"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g>有狀態更新:<xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"讀取電池計量器時發生問題"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"輕按即可瞭解詳情"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"未設定鬧鐘"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 787e7b0..e70a911 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"查看最近的訊息、未接來電和狀態更新"</string>
<string name="people_tile_title" msgid="6589377493334871272">"對話"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"零打擾模式已將通知暫停"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g>傳送了一則訊息:<xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g>傳送了一張圖片"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g>更新了狀態:<xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"讀取電池計量器時發生問題"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"輕觸即可瞭解詳情"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"未設定鬧鐘"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 5aa7ee0..883c746 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -1146,11 +1146,9 @@
<string name="people_tile_description" msgid="8154966188085545556">"Bona imiyalezo yakamuva, amakholi akuphuthile, nezibuyekezo zesimo"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Ingxoxo"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Kumiswe okuthi Ungaphazamisi"</string>
- <!-- no translation found for new_notification_text_content_description (2915029960094389291) -->
- <skip />
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"U-<xliff:g id="NAME">%1$s</xliff:g> uthumele umlayezo: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"U-<xliff:g id="NAME">%1$s</xliff:g> uthumele isithombe"</string>
- <!-- no translation found for new_status_content_description (6046637888641308327) -->
- <skip />
+ <string name="new_status_content_description" msgid="6046637888641308327">"U-<xliff:g id="NAME">%1$s</xliff:g> unesibuyekezo sesimo: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Kube khona inkinga ngokufunda imitha yakho yebhethri"</string>
<string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Thepha ukuze uthole olunye ulwazi"</string>
<string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"Akukho alamu esethiwe"</string>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 52627c2..542182b 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2728,7 +2728,7 @@
<!-- Device Controls strings -->
<!-- Device Controls, Quick Settings tile title [CHAR LIMIT=30] -->
- <string name="quick_controls_title">Home controls</string>
+ <string name="quick_controls_title">Device controls</string>
<!-- Controls management providers screen title [CHAR LIMIT=60]-->
<string name="controls_providers_title">Choose app to add controls</string>
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
index 4b3af34..fcf4e47 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
@@ -212,6 +212,7 @@
} else {
mView.setLineSpacingScale(mDefaultLineSpacing);
}
+ mView.refreshFormat();
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java
index 58b3865..ef3104a 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java
@@ -19,9 +19,9 @@
import android.annotation.FloatRange;
import android.annotation.IntRange;
import android.content.Context;
+import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
-import android.icu.text.DateTimePatternGenerator;
import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.widget.TextView;
@@ -30,6 +30,7 @@
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import java.util.Calendar;
+import java.util.Locale;
import java.util.TimeZone;
import kotlin.Unit;
@@ -41,8 +42,6 @@
public class AnimatableClockView extends TextView {
private static final CharSequence DOUBLE_LINE_FORMAT_12_HOUR = "hh\nmm";
private static final CharSequence DOUBLE_LINE_FORMAT_24_HOUR = "HH\nmm";
- private static final CharSequence SINGLE_LINE_FORMAT_12_HOUR = "h:mm";
- private static final CharSequence SINGLE_LINE_FORMAT_24_HOUR = "HH:mm";
private static final long DOZE_ANIM_DURATION = 300;
private static final long APPEAR_ANIM_DURATION = 350;
private static final long CHARGE_ANIM_DURATION_PHASE_0 = 500;
@@ -259,25 +258,47 @@
}
void refreshFormat() {
+ Patterns.update(mContext);
+
final boolean use24HourFormat = DateFormat.is24HourFormat(getContext());
if (mIsSingleLine && use24HourFormat) {
- mFormat = SINGLE_LINE_FORMAT_24_HOUR;
+ mFormat = Patterns.sClockView24;
} else if (!mIsSingleLine && use24HourFormat) {
mFormat = DOUBLE_LINE_FORMAT_24_HOUR;
} else if (mIsSingleLine && !use24HourFormat) {
- mFormat = SINGLE_LINE_FORMAT_12_HOUR;
+ mFormat = Patterns.sClockView12;
} else {
mFormat = DOUBLE_LINE_FORMAT_12_HOUR;
}
- mDescFormat = getBestDateTimePattern(getContext(), use24HourFormat ? "Hm" : "hm");
+ mDescFormat = use24HourFormat ? Patterns.sClockView24 : Patterns.sClockView12;
refreshTime();
}
- private static String getBestDateTimePattern(Context context, String skeleton) {
- DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(
- context.getResources().getConfiguration().locale);
- return dtpg.getBestPattern(skeleton);
+ // DateFormat.getBestDateTimePattern is extremely expensive, and refresh is called often.
+ // This is an optimization to ensure we only recompute the patterns when the inputs change.
+ private static final class Patterns {
+ static String sClockView12;
+ static String sClockView24;
+ static String sCacheKey;
+
+ static void update(Context context) {
+ final Locale locale = Locale.getDefault();
+ final Resources res = context.getResources();
+ final String clockView12Skel = res.getString(R.string.clock_12hr_format);
+ final String clockView24Skel = res.getString(R.string.clock_24hr_format);
+ final String key = locale.toString() + clockView12Skel + clockView24Skel;
+ if (key.equals(sCacheKey)) return;
+ sClockView12 = DateFormat.getBestDateTimePattern(locale, clockView12Skel);
+
+ // CLDR insists on adding an AM/PM indicator even though it wasn't in the skeleton
+ // format. The following code removes the AM/PM indicator if we didn't want it.
+ if (!clockView12Skel.contains("a")) {
+ sClockView12 = sClockView12.replaceAll("a", "").trim();
+ }
+ sClockView24 = DateFormat.getBestDateTimePattern(locale, clockView24Skel);
+ sCacheKey = key;
+ }
}
interface DozeStateGetter {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 781f34bf..632919a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -20,9 +20,7 @@
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import android.app.WallpaperManager;
-import android.content.res.Resources;
import android.text.TextUtils;
-import android.text.format.DateFormat;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
@@ -367,37 +365,6 @@
return mColorExtractor.getColors(WallpaperManager.FLAG_LOCK);
}
- // DateFormat.getBestDateTimePattern is extremely expensive, and refresh is called often.
- // This is an optimization to ensure we only recompute the patterns when the inputs change.
- private static final class Patterns {
- static String sClockView12;
- static String sClockView24;
- static String sCacheKey;
-
- static void update(Resources res) {
- final Locale locale = Locale.getDefault();
- final String clockView12Skel = res.getString(R.string.clock_12hr_format);
- final String clockView24Skel = res.getString(R.string.clock_24hr_format);
- final String key = locale.toString() + clockView12Skel + clockView24Skel;
- if (key.equals(sCacheKey)) return;
-
- sClockView12 = DateFormat.getBestDateTimePattern(locale, clockView12Skel);
- // CLDR insists on adding an AM/PM indicator even though it wasn't in the skeleton
- // format. The following code removes the AM/PM indicator if we didn't want it.
- if (!clockView12Skel.contains("a")) {
- sClockView12 = sClockView12.replaceAll("a", "").trim();
- }
-
- sClockView24 = DateFormat.getBestDateTimePattern(locale, clockView24Skel);
-
- // Use fancy colon.
- sClockView24 = sClockView24.replace(':', '\uee01');
- sClockView12 = sClockView12.replace(':', '\uee01');
-
- sCacheKey = key;
- }
- }
-
private int getCurrentLayoutDirection() {
return TextUtils.getLayoutDirectionFromLocale(Locale.getDefault());
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
index 568bea0..62411db 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
@@ -54,6 +54,7 @@
private CharSequence mMessage;
private ColorStateList mNextMessageColorState = ColorStateList.valueOf(DEFAULT_COLOR);
private boolean mBouncerVisible;
+ private boolean mAltBouncerShowing;
public KeyguardMessageArea(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -144,7 +145,8 @@
void update() {
CharSequence status = mMessage;
- setVisibility(TextUtils.isEmpty(status) || !mBouncerVisible ? INVISIBLE : VISIBLE);
+ setVisibility(TextUtils.isEmpty(status) || (!mBouncerVisible && !mAltBouncerShowing)
+ ? INVISIBLE : VISIBLE);
setText(status);
ColorStateList colorState = mDefaultColorState;
if (mNextMessageColorState.getDefaultColor() != DEFAULT_COLOR) {
@@ -159,6 +161,16 @@
}
/**
+ * Set whether the alt bouncer is showing
+ */
+ void setAltBouncerShowing(boolean showing) {
+ if (mAltBouncerShowing != showing) {
+ mAltBouncerShowing = showing;
+ update();
+ }
+ }
+
+ /**
* Runnable used to delay accessibility announcements.
*/
private static class AnnounceRunnable implements Runnable {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java
index 6e40f02..51ded3f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java
@@ -28,7 +28,7 @@
public class KeyguardMessageAreaController extends ViewController<KeyguardMessageArea> {
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final ConfigurationController mConfigurationController;
-
+ private boolean mAltBouncerShowing;
private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
public void onFinishedGoingToSleep(int why) {
@@ -81,6 +81,13 @@
mKeyguardUpdateMonitor.removeCallback(mInfoCallback);
}
+ /**
+ * Set whether alt bouncer is showing
+ */
+ public void setAltBouncerShowing(boolean showing) {
+ mView.setAltBouncerShowing(showing);
+ }
+
public void setMessage(CharSequence s) {
mView.setMessage(s);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconView.java b/packages/SystemUI/src/com/android/keyguard/LockIconView.java
index c425ddf..c1d448d 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconView.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconView.java
@@ -43,7 +43,7 @@
mSensorRect = new RectF();
}
- void setLocation(@NonNull PointF center, int radius) {
+ void setCenterLocation(@NonNull PointF center, int radius) {
mLockIconCenter = center;
mRadius = radius;
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index f3fbc50..62cb4b9 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -98,7 +98,7 @@
private float mHeightPixels;
private float mWidthPixels;
private float mDensity;
- private int mIndicationBottomPadding;
+ private int mKgBottomAreaHeight;
private boolean mShowUnlockIcon;
private boolean mShowLockIcon;
@@ -280,7 +280,9 @@
mWidthPixels = metrics.widthPixels;
mHeightPixels = metrics.heightPixels;
mDensity = metrics.density;
- mIndicationBottomPadding = mView.getContext().getResources().getDimensionPixelSize(
+ mKgBottomAreaHeight = mView.getContext().getResources().getDimensionPixelSize(
+ R.dimen.keyguard_indication_margin_bottom)
+ + mView.getContext().getResources().getDimensionPixelSize(
R.dimen.keyguard_indication_bottom_padding);
updateLockIconLocation();
}
@@ -288,15 +290,15 @@
private void updateLockIconLocation() {
if (mHasUdfps) {
FingerprintSensorPropertiesInternal props = mAuthController.getUdfpsProps().get(0);
- mView.setLocation(new PointF(props.sensorLocationX, props.sensorLocationY),
+ mView.setCenterLocation(new PointF(props.sensorLocationX, props.sensorLocationY),
props.sensorRadius);
} else {
final float distAboveKgBottomArea = 12 * mDensity;
final float radius = 36 * mDensity;
- mView.setLocation(
+ mView.setCenterLocation(
new PointF(mWidthPixels / 2,
- mHeightPixels - mIndicationBottomPadding - distAboveKgBottomArea - radius),
- (int) radius);
+ mHeightPixels - mKgBottomAreaHeight - distAboveKgBottomArea
+ - radius / 2), (int) radius);
}
mView.getHitRect(mSensorTouchLocation);
diff --git a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
index b80f8bd..b159714 100644
--- a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
@@ -21,6 +21,7 @@
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -87,7 +88,7 @@
/**
* The raw text size, will be multiplied by the scaled density when drawn
*/
- private final int mTextHeightRaw;
+ private int mTextHeightRaw;
private final int mGravity;
private ArrayList<CharState> mTextChars = new ArrayList<>();
private String mText = "";
@@ -147,6 +148,7 @@
} finally {
a.recycle();
}
+
mDrawPaint.setFlags(Paint.SUBPIXEL_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
mDrawPaint.setTextAlign(Paint.Align.CENTER);
mDrawPaint.setTypeface(Typeface.create(
@@ -164,6 +166,12 @@
}
@Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ mTextHeightRaw = getContext().getResources().getInteger(
+ R.integer.scaled_password_text_size);
+ }
+
+ @Override
protected void onDraw(Canvas canvas) {
float totalDrawingWidth = getDrawingWidth();
float currentDrawPosition;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java
index c4f5880..205054d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java
@@ -90,6 +90,7 @@
}
@Modality private int mActiveSensorType = TYPE_FACE;
+ @Nullable private ModalityListener mModalityListener;
@Nullable private FingerprintSensorPropertiesInternal mFingerprintSensorProps;
@Nullable private UdfpsDialogMeasureAdapter mUdfpsMeasureAdapter;
@@ -115,6 +116,10 @@
return mFingerprintSensorProps.isAnyUdfpsType();
}
+ void setModalityListener(@NonNull ModalityListener listener) {
+ mModalityListener = listener;
+ }
+
void setFingerprintSensorProps(@NonNull FingerprintSensorPropertiesInternal sensorProps) {
mFingerprintSensorProps = sensorProps;
}
@@ -182,11 +187,16 @@
@Override
public void updateState(@BiometricState int newState) {
if (mState == STATE_HELP || mState == STATE_ERROR) {
+ @Modality final int currentType = mActiveSensorType;
mActiveSensorType = TYPE_FINGERPRINT;
setRequireConfirmation(false);
mConfirmButton.setEnabled(false);
mConfirmButton.setVisibility(View.GONE);
+
+ if (mModalityListener != null && currentType != mActiveSensorType) {
+ mModalityListener.onModalitySwitched(currentType, mActiveSensorType);
+ }
}
super.updateState(newState);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
index d5f7495..bebf813 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
@@ -759,6 +759,9 @@
// Restore positive button(s) state
mConfirmButton.setVisibility(
mSavedState.getInt(AuthDialog.KEY_BIOMETRIC_CONFIRM_VISIBILITY));
+ if (mConfirmButton.getVisibility() == View.GONE) {
+ setRequireConfirmation(false);
+ }
mTryAgainButton.setVisibility(
mSavedState.getInt(AuthDialog.KEY_BIOMETRIC_TRY_AGAIN_VISIBILITY));
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index fd1313f..3f61d3c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -24,7 +24,6 @@
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.PixelFormat;
-import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricAuthenticator.Modality;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.PromptInfo;
@@ -37,6 +36,7 @@
import android.os.Looper;
import android.os.UserManager;
import android.util.Log;
+import android.view.Display;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -356,6 +356,12 @@
(AuthBiometricFaceToFingerprintView) factory.inflate(
R.layout.auth_biometric_face_to_fingerprint_view, null, false);
faceToFingerprintView.setFingerprintSensorProps(fingerprintSensorProps);
+ faceToFingerprintView.setModalityListener(new ModalityListener() {
+ @Override
+ public void onModalitySwitched(int oldModality, int newModality) {
+ maybeUpdatePositionForUdfps(true /* invalidate */);
+ }
+ });
mBiometricView = faceToFingerprintView;
} else {
Log.e(TAG, "Fingerprint props not found for sensor ID: " + fingerprintSensorId);
@@ -471,6 +477,11 @@
}
@Override
+ public void onOrientationChanged() {
+ maybeUpdatePositionForUdfps(true /* invalidate */);
+ }
+
+ @Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
onAttachedToWindowInternal();
@@ -489,9 +500,7 @@
+ mConfig.mPromptInfo.getAuthenticators());
}
- if (shouldUpdatePositionForUdfps()) {
- updatePositionForUdfps();
- }
+ maybeUpdatePositionForUdfps(false /* invalidate */);
if (mConfig.mSkipIntro) {
mContainerState = STATE_SHOWING;
@@ -536,14 +545,14 @@
}
}
- private boolean shouldUpdatePositionForUdfps() {
- if (mBiometricView instanceof AuthBiometricUdfpsView) {
+ private static boolean shouldUpdatePositionForUdfps(@NonNull View view) {
+ if (view instanceof AuthBiometricUdfpsView) {
return true;
}
- if (mBiometricView instanceof AuthBiometricFaceToFingerprintView) {
+ if (view instanceof AuthBiometricFaceToFingerprintView) {
AuthBiometricFaceToFingerprintView faceToFingerprintView =
- (AuthBiometricFaceToFingerprintView) mBiometricView;
+ (AuthBiometricFaceToFingerprintView) view;
return faceToFingerprintView.getActiveSensorType() == TYPE_FINGERPRINT
&& faceToFingerprintView.isFingerprintUdfps();
}
@@ -551,8 +560,16 @@
return false;
}
- private void updatePositionForUdfps() {
- final int displayRotation = getDisplay().getRotation();
+ private boolean maybeUpdatePositionForUdfps(boolean invalidate) {
+ final Display display = getDisplay();
+ if (display == null) {
+ return false;
+ }
+ if (!shouldUpdatePositionForUdfps(mBiometricView)) {
+ return false;
+ }
+
+ final int displayRotation = display.getRotation();
switch (displayRotation) {
case Surface.ROTATION_0:
mPanelController.setPosition(AuthPanelController.POSITION_BOTTOM);
@@ -576,6 +593,13 @@
setScrollViewGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
break;
}
+
+ if (invalidate) {
+ mPanelView.invalidateOutline();
+ mBiometricView.requestLayout();
+ }
+
+ return true;
}
private void setScrollViewGravity(int gravity) {
@@ -626,13 +650,6 @@
@Override
public void onAuthenticationFailed(@Modality int modality, String failureReason) {
mBiometricView.onAuthenticationFailed(modality, failureReason);
- if (mBiometricView instanceof AuthBiometricFaceToFingerprintView
- && ((AuthBiometricFaceToFingerprintView) mBiometricView).isFingerprintUdfps()
- && modality == BiometricAuthenticator.TYPE_FACE) {
- updatePositionForUdfps();
- mPanelView.invalidateOutline();
- mBiometricView.requestLayout();
- }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 7947241..37b0625 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -30,7 +30,6 @@
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.graphics.PointF;
-import android.graphics.RectF;
import android.hardware.biometrics.BiometricAuthenticator.Modality;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager.Authenticators;
@@ -49,7 +48,10 @@
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
+import android.view.Display;
import android.view.MotionEvent;
+import android.view.OrientationEventListener;
+import android.view.Surface;
import android.view.WindowManager;
import com.android.internal.R;
@@ -97,17 +99,15 @@
@VisibleForTesting
AuthDialog mCurrentDialog;
- private WindowManager mWindowManager;
- @Nullable
- private UdfpsController mUdfpsController;
- @Nullable
- private IUdfpsHbmListener mUdfpsHbmListener;
- @Nullable
- private SidefpsController mSidefpsController;
+ @NonNull private final WindowManager mWindowManager;
+ @Nullable private UdfpsController mUdfpsController;
+ @Nullable private IUdfpsHbmListener mUdfpsHbmListener;
+ @Nullable private SidefpsController mSidefpsController;
@VisibleForTesting
TaskStackListener mTaskStackListener;
@VisibleForTesting
IBiometricSysuiReceiver mReceiver;
+ @NonNull private final BiometricOrientationEventListener mOrientationListener;
@Nullable private final List<FaceSensorPropertiesInternal> mFaceProps;
@Nullable private List<FingerprintSensorPropertiesInternal> mFpProps;
@Nullable private List<FingerprintSensorPropertiesInternal> mUdfpsProps;
@@ -120,6 +120,46 @@
}
}
+ private class BiometricOrientationEventListener extends OrientationEventListener {
+ @Surface.Rotation private int mLastRotation = ORIENTATION_UNKNOWN;
+
+ BiometricOrientationEventListener(Context context) {
+ super(context);
+
+ final Display display = context.getDisplay();
+ if (display != null) {
+ mLastRotation = display.getRotation();
+ }
+ }
+
+ @Override
+ public void onOrientationChanged(int orientation) {
+ if (orientation == ORIENTATION_UNKNOWN) {
+ return;
+ }
+
+ final Display display = mContext.getDisplay();
+ if (display == null) {
+ return;
+ }
+
+ final int rotation = display.getRotation();
+ if (mLastRotation != rotation) {
+ mLastRotation = rotation;
+
+ if (mCurrentDialog != null) {
+ mCurrentDialog.onOrientationChanged();
+ }
+ if (mUdfpsController != null) {
+ mUdfpsController.onOrientationChanged();
+ }
+ if (mSidefpsController != null) {
+ mSidefpsController.onOrientationChanged();
+ }
+ }
+ }
+ }
+
@NonNull
private final IFingerprintAuthenticatorsRegisteredCallback
mFingerprintAuthenticatorsRegisteredCallback =
@@ -192,6 +232,7 @@
Log.w(TAG, "Evicting client due to: " + topPackage);
mCurrentDialog.dismissWithoutCallback(true /* animate */);
mCurrentDialog = null;
+
if (mReceiver != null) {
mReceiver.onDialogDismissed(
BiometricPrompt.DISMISSED_REASON_USER_CANCEL,
@@ -342,15 +383,6 @@
/**
* @return where the UDFPS exists on the screen in pixels in portrait mode.
*/
- @Nullable public RectF getUdfpsRegion() {
- return mUdfpsController == null
- ? null
- : mUdfpsController.getSensorLocation();
- }
-
- /**
- * @return where the UDFPS exists on the screen in pixels in portrait mode.
- */
@Nullable public PointF getUdfpsSensorLocation() {
if (mUdfpsController == null) {
return null;
@@ -422,8 +454,10 @@
}
@Inject
- public AuthController(Context context, CommandQueue commandQueue,
+ public AuthController(Context context,
+ CommandQueue commandQueue,
ActivityTaskManager activityTaskManager,
+ @NonNull WindowManager windowManager,
@Nullable FingerprintManager fingerprintManager,
@Nullable FaceManager faceManager,
Provider<UdfpsController> udfpsControllerFactory,
@@ -435,6 +469,9 @@
mFaceManager = faceManager;
mUdfpsControllerFactory = udfpsControllerFactory;
mSidefpsControllerFactory = sidefpsControllerFactory;
+ mWindowManager = windowManager;
+ mOrientationListener = new BiometricOrientationEventListener(context);
+ mOrientationListener.enable();
mFaceProps = mFaceManager != null ? mFaceManager.getSensorPropertiesInternal() : null;
@@ -462,7 +499,6 @@
@Override
public void start() {
mCommandQueue.addCallback(this);
- mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
if (mFingerprintManager != null) {
mFingerprintManager.addAuthenticatorsRegisteredCallback(
@@ -633,6 +669,17 @@
}
/**
+ * Whether the user's finger is currently on udfps attempting to authenticate.
+ */
+ public boolean isUdfpsFingerDown() {
+ if (mUdfpsController == null) {
+ return false;
+ }
+
+ return mUdfpsController.isFingerDown();
+ }
+
+ /**
* Whether the passed userId has enrolled face auth.
*/
public boolean isFaceAuthEnrolled(int userId) {
@@ -715,15 +762,6 @@
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- // UdfpsController is not BiometricPrompt-specific. It can be active for keyguard or
- // enrollment.
- if (mUdfpsController != null) {
- mUdfpsController.onConfigurationChanged();
- }
-
- if (mSidefpsController != null) {
- mSidefpsController.onConfigurationChanged();
- }
// Save the state of the current dialog (buttons showing, etc)
if (mCurrentDialog != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
index ff31e49..fa5213e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
@@ -156,4 +156,12 @@
* @return true if device credential is allowed.
*/
boolean isAllowDeviceCredentials();
+
+ /**
+ * Called when the device's orientation changed and the dialog may need to do another
+ * layout. This is most relevant to UDFPS since configuration changes are not sent by
+ * the framework in equivalent cases (landscape to reverse landscape) but the dialog
+ * must remain fixed on the physical sensor location.
+ */
+ void onOrientationChanged();
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ModalityListener.java b/packages/SystemUI/src/com/android/systemui/biometrics/ModalityListener.java
new file mode 100644
index 0000000..c162f7d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ModalityListener.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 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.hardware.biometrics.BiometricAuthenticator.Modality;
+
+/**
+ * Listener for events related to modality changes during operations.
+ *
+ * Used by views such as {@link AuthBiometricFaceToFingerprintView} that support fallback style
+ * authentication.
+ */
+public interface ModalityListener {
+
+ /**
+ * The modality has changed. Called after the transition has been fully completed.
+ *
+ * @param oldModality original modality
+ * @param newModality current modality
+ */
+ default void onModalitySwitched(@Modality int oldModality, @Modality int newModality) {}
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
index a52296a..436e1e4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
@@ -137,8 +137,7 @@
}
}
-
- void onConfigurationChanged() {
+ void onOrientationChanged() {
// If mView is null or if view is hidden, then return.
if (mView == null || !mIsVisible) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index c5a0dfb..710aca0 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -650,7 +650,7 @@
return mCoreLayoutParams;
}
- void onConfigurationChanged() {
+ void onOrientationChanged() {
// When the configuration changes it's almost always necessary to destroy and re-create
// the overlay's window to pass it the new LayoutParams.
// Hiding the overlay will destroy its window. It's safe to hide the overlay regardless
@@ -663,6 +663,7 @@
private void showUdfpsOverlay(@NonNull ServerRequest request) {
mExecution.assertIsMainThread();
+
final int reason = request.mRequestReason;
if (mView == null) {
try {
@@ -751,22 +752,22 @@
}
private void hideUdfpsOverlay() {
- mFgExecutor.execute(() -> {
- if (mView != null) {
- Log.v(TAG, "hideUdfpsOverlay | removing window");
- // Reset the controller back to its starting state.
- onFingerUp();
- mWindowManager.removeView(mView);
- mView.setOnTouchListener(null);
- mView.setOnHoverListener(null);
- mView.setAnimationViewController(null);
- mAccessibilityManager.removeTouchExplorationStateChangeListener(
- mTouchExplorationStateChangeListener);
- mView = null;
- } else {
- Log.v(TAG, "hideUdfpsOverlay | the overlay is already hidden");
- }
- });
+ mExecution.assertIsMainThread();
+
+ if (mView != null) {
+ Log.v(TAG, "hideUdfpsOverlay | removing window");
+ // Reset the controller back to its starting state.
+ onFingerUp();
+ mWindowManager.removeView(mView);
+ mView.setOnTouchListener(null);
+ mView.setOnHoverListener(null);
+ mView.setAnimationViewController(null);
+ mAccessibilityManager.removeTouchExplorationStateChangeListener(
+ mTouchExplorationStateChangeListener);
+ mView = null;
+ } else {
+ Log.v(TAG, "hideUdfpsOverlay | the overlay is already hidden");
+ }
}
/**
@@ -821,6 +822,10 @@
mIsAodInterruptActive = false;
}
+ public boolean isFingerDown() {
+ return mOnFingerDown;
+ }
+
private void onFingerDown(int x, int y, float minor, float major) {
mExecution.assertIsMainThread();
if (mView == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
index 91cc149..3dab010 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
@@ -71,12 +71,6 @@
}
}
- @Override
- protected void onViewDetached() {
- super.onViewDetached();
- mEnrollHelper.setListener(null);
- }
-
@NonNull
@Override
public PointF getTouchTranslation() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 819de53..073e886 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -66,6 +66,7 @@
private boolean mHintShown;
private int mStatusBarState;
private float mTransitionToFullShadeProgress;
+ private float mLastDozeAmount;
/**
* hidden amount of pin/pattern/password bouncer
@@ -108,6 +109,7 @@
updateFaceDetectRunning(mKeyguardUpdateMonitor.isFaceDetectionRunning());
final float dozeAmount = mStatusBarStateController.getDozeAmount();
+ mLastDozeAmount = dozeAmount;
mStateListener.onDozeAmountChanged(dozeAmount, dozeAmount);
mStatusBarStateController.addCallback(mStateListener);
@@ -287,8 +289,11 @@
new StatusBarStateController.StateListener() {
@Override
public void onDozeAmountChanged(float linear, float eased) {
- if (linear != 0) showUdfpsBouncer(false);
+ if (mLastDozeAmount < linear) {
+ showUdfpsBouncer(false);
+ }
mView.onDozeAmountChanged(linear, eased);
+ mLastDozeAmount = linear;
updatePauseAuth();
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 15f7a12..75f77bf 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -175,7 +175,7 @@
private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
private static final long KEYGUARD_DONE_PENDING_TIMEOUT_MS = 3000;
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES;
private final static String TAG = "KeyguardViewMediator";
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 8c2c373..a318073 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -140,9 +140,11 @@
updateAnimators();
}
-
- public void onQsScrollingChanged() {
- // Lazily update animators whenever the scrolling changes
+ /**
+ * Request an update to the animators. This will update them lazily next time the position
+ * is changed.
+ */
+ public void requestAnimatorUpdate() {
mNeedsAnimatorUpdate = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 0d91f29..36b4ee9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -173,7 +173,7 @@
mQSPanelScrollView.setOnScrollChangeListener(
(v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
// Lazily update animators whenever the scrolling changes
- mQSAnimator.onQsScrollingChanged();
+ mQSAnimator.requestAnimatorUpdate();
mHeader.setExpandedScrollAmount(scrollY);
if (mScrollListener != null) {
mScrollListener.onQsPanelScrollChanged(scrollY);
@@ -215,6 +215,14 @@
setQsExpansion(mLastQSExpansion, mLastHeaderTranslation);
}
});
+ mQSPanelController.setUsingHorizontalLayoutChangeListener(
+ () -> {
+ // The hostview may be faded out in the horizontal layout. Let's make sure to
+ // reset the alpha when switching layouts. This is fine since the animator will
+ // update the alpha if it's not supposed to be 1.0f
+ mQSPanelController.getMediaHost().getHostView().setAlpha(1.0f);
+ mQSAnimator.requestAnimatorUpdate();
+ });
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index 7a09826..4739a3f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -103,6 +103,9 @@
private boolean mUsingHorizontalLayout;
+ @Nullable
+ private Runnable mUsingHorizontalLayoutChangedListener;
+
protected QSPanelControllerBase(
T view,
QSTileHost host,
@@ -135,6 +138,13 @@
mQSLogger.logAllTilesChangeListening(mView.isListening(), mView.getDumpableTag(), "");
}
+ /**
+ * @return the media host for this panel
+ */
+ public MediaHost getMediaHost() {
+ return mMediaHost;
+ }
+
@Override
protected void onViewAttached() {
mQsTileRevealController = createTileRevealController();
@@ -303,6 +313,9 @@
mUsingHorizontalLayout = horizontal;
mView.setUsingHorizontalLayout(mUsingHorizontalLayout, mMediaHost.getHostView(), force);
updateMediaDisappearParameters();
+ if (mUsingHorizontalLayoutChangedListener != null) {
+ mUsingHorizontalLayoutChangedListener.run();
+ }
return true;
}
return false;
@@ -386,6 +399,13 @@
mMediaVisibilityChangedListener = listener;
}
+ /**
+ * Add a listener when the horizontal layout changes
+ */
+ public void setUsingHorizontalLayoutChangeListener(Runnable listener) {
+ mUsingHorizontalLayoutChangedListener = listener;
+ }
+
/** */
public static final class TileRecord extends QSPanel.Record {
public QSTile tile;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
index f13576c..bf72b77 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
@@ -16,6 +16,8 @@
package com.android.systemui.qs.tiles;
+import static android.hardware.SensorPrivacyManager.Sources.QS_TILE;
+
import android.content.Intent;
import android.hardware.SensorPrivacyManager.Sensors.Sensor;
import android.os.Handler;
@@ -87,12 +89,12 @@
protected void handleClick(@Nullable View view) {
if (mKeyguard.isMethodSecure() && mKeyguard.isShowing()) {
mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
- mSensorPrivacyController.setSensorBlocked(getSensorId(),
+ mSensorPrivacyController.setSensorBlocked(QS_TILE, getSensorId(),
!mSensorPrivacyController.isSensorBlocked(getSensorId()));
});
return;
}
- mSensorPrivacyController.setSensorBlocked(getSensorId(),
+ mSensorPrivacyController.setSensorBlocked(QS_TILE, getSensorId(),
!mSensorPrivacyController.isSensorBlocked(getSensorId()));
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
index cb6ac47..af0141c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
@@ -80,6 +80,7 @@
private View mSave;
private View mEdit;
private View mShare;
+ private View mDelete;
private CropView mCropView;
private MagnifierView mMagnifierView;
private ScrollCaptureResponse mScrollCaptureResponse;
@@ -120,18 +121,24 @@
mSave = requireViewById(R.id.save);
mEdit = requireViewById(R.id.edit);
mShare = requireViewById(R.id.share);
+ mDelete = requireViewById(R.id.delete);
mCropView = requireViewById(R.id.crop_view);
mMagnifierView = requireViewById(R.id.magnifier);
mCropView.setCropInteractionListener(mMagnifierView);
mTransitionView = requireViewById(R.id.transition);
mEnterTransitionView = requireViewById(R.id.enter_transition);
- requireViewById(R.id.cancel).setOnClickListener(v -> finishAndRemoveTask());
-
mSave.setOnClickListener(this::onClicked);
mEdit.setOnClickListener(this::onClicked);
mShare.setOnClickListener(this::onClicked);
+ // Only show the delete button if we have something to delete (should typically be the case)
+ if (getIntent().getData() != null) {
+ mDelete.setOnClickListener(this::onClicked);
+ } else {
+ mDelete.setVisibility(View.GONE);
+ }
+
mPreview.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
updateImageDimensions());
@@ -321,6 +328,7 @@
mSave.setEnabled(enabled);
mEdit.setEnabled(enabled);
mShare.setEnabled(enabled);
+ mDelete.setEnabled(enabled);
}
private void doEdit(Uri uri) {
@@ -375,6 +383,11 @@
} else if (id == R.id.share) {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_SHARE);
startExport(PendingAction.SHARE);
+ } else if (id == R.id.delete) {
+ mBackgroundExecutor.execute(() -> {
+ getContentResolver().delete(getIntent().getData(), null);
+ finishAndRemoveTask();
+ });
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 16872b0..52b393f 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -264,6 +264,7 @@
private Animator mScreenshotAnimation;
private RequestCallback mCurrentRequestCallback;
+ private Uri mLatestUriSaved;
private final Handler mScreenshotHandler = new Handler(Looper.getMainLooper()) {
@Override
@@ -546,7 +547,6 @@
mAccessibilityManager.sendAccessibilityEvent(event);
}
-
if (mScreenshotView.isAttachedToWindow()) {
// if we didn't already dismiss for another reason
if (!mScreenshotView.isDismissing()) {
@@ -563,6 +563,7 @@
.getWindowInsets().getDisplayCutout());
mScreenBitmap = screenshot;
+ mLatestUriSaved = null;
if (!isUserSetupComplete()) {
Log.w(TAG, "User setup not complete, displaying toast only");
@@ -700,6 +701,7 @@
longScreenshot));
final Intent intent = new Intent(mContext, LongScreenshotActivity.class);
+ intent.setData(mLatestUriSaved);
intent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -889,6 +891,8 @@
resetTimeout();
+ mLatestUriSaved = imageData.uri;
+
if (imageData.uri != null) {
mScreenshotHandler.post(() -> {
if (mScreenshotAnimation != null && mScreenshotAnimation.isRunning()) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index 804e299..e9e62f2 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -868,7 +868,8 @@
matrix.setScale(scale, scale);
matrix.postTranslate(-scrollableArea.left * scale, -scrollableArea.top * scale);
- mScrollablePreview.setTranslationX(scale * scrollableArea.left);
+ mScrollablePreview.setTranslationX(scale
+ * (mDirectionLTR ? scrollableArea.left : scrollableArea.right - getWidth()));
mScrollablePreview.setTranslationY(scale * scrollableArea.top);
mScrollablePreview.setImageMatrix(matrix);
mScrollablePreview.setImageBitmap(screenBitmap);
diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
index a79316d..2477534 100644
--- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
@@ -23,6 +23,7 @@
import android.hardware.SensorPrivacyManager
import android.hardware.SensorPrivacyManager.EXTRA_ALL_SENSORS
import android.hardware.SensorPrivacyManager.EXTRA_SENSOR
+import android.hardware.SensorPrivacyManager.Sources.DIALOG
import android.os.Bundle
import android.os.Handler
import android.text.Html
@@ -225,10 +226,10 @@
private fun disableSensorPrivacy() {
if (sensor == ALL_SENSORS) {
- sensorPrivacyController.setSensorBlocked(MICROPHONE, false)
- sensorPrivacyController.setSensorBlocked(CAMERA, false)
+ sensorPrivacyController.setSensorBlocked(DIALOG, MICROPHONE, false)
+ sensorPrivacyController.setSensorBlocked(DIALOG, CAMERA, false)
} else {
- sensorPrivacyController.setSensorBlocked(sensor, false)
+ sensorPrivacyController.setSensorBlocked(DIALOG, sensor, false)
}
unsuppressImmediately = true
setResult(RESULT_OK)
diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java b/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java
index 9d101ef..8cd3632 100644
--- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java
@@ -18,6 +18,7 @@
import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
+import static android.hardware.SensorPrivacyManager.Sources.OTHER;
import android.hardware.SensorPrivacyManager;
import android.os.Bundle;
@@ -119,10 +120,10 @@
com.android.internal.R.string.sensor_privacy_start_use_dialog_turn_on_button);
unblockButton.setOnClickListener(v -> {
if (mSensor == ALL_SENSORS) {
- mSensorPrivacyController.setSensorBlocked(CAMERA, false);
- mSensorPrivacyController.setSensorBlocked(MICROPHONE, false);
+ mSensorPrivacyController.setSensorBlocked(OTHER, CAMERA, false);
+ mSensorPrivacyController.setSensorBlocked(OTHER, MICROPHONE, false);
} else {
- mSensorPrivacyController.setSensorBlocked(mSensor, false);
+ mSensorPrivacyController.setSensorBlocked(OTHER, mSensor, false);
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 5afdc38..44399a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -597,8 +597,8 @@
if (mDozing && !TextUtils.isEmpty(mTransientIndication)) {
// Make sure this doesn't get stuck and burns in. Acquire wakelock until its cleared.
mWakeLock.setAcquired(true);
- hideTransientIndicationDelayed(BaseKeyguardCallback.HIDE_DELAY_MS);
}
+ hideTransientIndicationDelayed(BaseKeyguardCallback.HIDE_DELAY_MS);
updateIndication(false);
}
@@ -797,12 +797,15 @@
}
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
- String message = mContext.getString(R.string.keyguard_retry);
- mStatusBarKeyguardViewManager.showBouncerMessage(message, mInitialTextColorState);
+ if (mStatusBarKeyguardViewManager.isShowingAlternateAuth()) {
+ return; // udfps affordance is highlighted, no need to surface face auth error
+ } else {
+ String message = mContext.getString(R.string.keyguard_retry);
+ mStatusBarKeyguardViewManager.showBouncerMessage(message, mInitialTextColorState);
+ }
} else if (mKeyguardUpdateMonitor.isScreenOn()) {
showTransientIndication(mContext.getString(R.string.keyguard_unlock),
false /* isError */, true /* hideOnScreenOff */);
- hideTransientIndicationDelayed(BaseKeyguardCallback.HIDE_DELAY_MS);
}
}
@@ -862,7 +865,6 @@
if (mDozing) {
if (!wasPluggedIn && mPowerPluggedIn) {
showTransientIndication(computePowerIndication());
- hideTransientIndicationDelayed(HIDE_DELAY_MS);
} else if (wasPluggedIn && !mPowerPluggedIn) {
hideTransientIndication();
}
@@ -882,23 +884,19 @@
return;
}
- if (biometricSourceType == BiometricSourceType.FACE
- && shouldSuppressFaceMsgAndShowTryFingerprintMsg()) {
- // suggest trying fingerprint
- showTransientIndication(R.string.keyguard_try_fingerprint);
- return;
- }
-
boolean showSwipeToUnlock =
msgId == KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
mStatusBarKeyguardViewManager.showBouncerMessage(helpString,
mInitialTextColorState);
} else if (mKeyguardUpdateMonitor.isScreenOn()) {
- showTransientIndication(helpString, false /* isError */, showSwipeToUnlock);
- if (!showSwipeToUnlock) {
- hideTransientIndicationDelayed(TRANSIENT_BIOMETRIC_ERROR_TIMEOUT);
+ if (biometricSourceType == BiometricSourceType.FACE
+ && shouldSuppressFaceMsgAndShowTryFingerprintMsg()) {
+ // suggest trying fingerprint
+ showTransientIndication(R.string.keyguard_try_fingerprint);
+ return;
}
+ showTransientIndication(helpString, false /* isError */, showSwipeToUnlock);
}
if (showSwipeToUnlock) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SWIPE_UP_TO_UNLOCK),
@@ -913,7 +911,9 @@
return;
}
if (biometricSourceType == BiometricSourceType.FACE
- && shouldSuppressFaceMsgAndShowTryFingerprintMsg()) {
+ && shouldSuppressFaceMsgAndShowTryFingerprintMsg()
+ && !mStatusBarKeyguardViewManager.isBouncerShowing()
+ && mKeyguardUpdateMonitor.isScreenOn()) {
// suggest trying fingerprint
showTransientIndication(R.string.keyguard_try_fingerprint);
return;
@@ -926,6 +926,11 @@
&& mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) {
// suggest trying fingerprint
showTransientIndication(R.string.keyguard_try_fingerprint);
+ } else if (mStatusBarKeyguardViewManager.isShowingAlternateAuth()) {
+ mStatusBarKeyguardViewManager.showBouncerMessage(
+ mContext.getResources().getString(R.string.keyguard_try_fingerprint),
+ mInitialTextColorState
+ );
} else {
// suggest swiping up to unlock (try face auth again or swipe up to bouncer)
showSwipeUpToUnlock();
@@ -935,8 +940,6 @@
} else if (mKeyguardUpdateMonitor.isScreenOn()) {
showTransientIndication(errString, /* isError */ true,
/* hideOnScreenOff */ true);
- // We want to keep this message around in case the screen was off
- hideTransientIndicationDelayed(HIDE_DELAY_MS);
} else {
mMessageToShowOnScreenOn = errString;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
index 8e24890..86c90c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
@@ -25,6 +25,7 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
+import com.android.systemui.statusbar.notification.stack.ViewState;
public class FooterView extends StackScrollerDecorView {
private final int mClearAllTopPadding;
@@ -122,6 +123,14 @@
public boolean hideContent;
@Override
+ public void copyFrom(ViewState viewState) {
+ super.copyFrom(viewState);
+ if (viewState instanceof FooterViewState) {
+ hideContent = ((FooterViewState) viewState).hideContent;
+ }
+ }
+
+ @Override
public void applyToView(View view) {
super.applyToView(view);
if (view instanceof FooterView) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index ead87a4..4ad7202 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -682,8 +682,7 @@
boolean showDismissView = mClearAllEnabled &&
mController.hasActiveClearableNotifications(ROWS_ALL);
RemoteInputController remoteInputController = mRemoteInputManager.getController();
- boolean showFooterView = (showDismissView || mController.hasActiveNotifications())
- && mEmptyShadeView.getVisibility() == GONE
+ boolean showFooterView = (showDismissView || getVisibleNotificationCount() > 0)
&& mStatusBarState != StatusBarState.KEYGUARD
&& !mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()
&& (remoteInputController == null || !remoteInputController.isRemoteInputActive());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index add6fda..3fc8b8d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -399,12 +399,15 @@
if (view instanceof FooterView) {
final boolean shadeClosed = !ambientState.isShadeExpanded();
final boolean isShelfShowing = algorithmState.firstViewInShelf != null;
-
- final float footerEnd = algorithmState.mCurrentExpandedYPosition
- + view.getIntrinsicHeight();
- final boolean noSpaceForFooter = footerEnd > ambientState.getStackEndHeight();
- ((FooterView.FooterViewState) viewState).hideContent =
- shadeClosed || isShelfShowing || noSpaceForFooter;
+ if (shadeClosed) {
+ viewState.hidden = true;
+ } else {
+ final float footerEnd = algorithmState.mCurrentExpandedYPosition
+ + view.getIntrinsicHeight();
+ final boolean noSpaceForFooter = footerEnd > ambientState.getStackEndHeight();
+ ((FooterView.FooterViewState) viewState).hideContent =
+ isShelfShowing || noSpaceForFooter;
+ }
} else {
if (view != ambientState.getTrackedHeadsUpRow()) {
if (ambientState.isExpansionChanging()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 20e6f60..6d5c536 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -39,6 +39,7 @@
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.KeyguardViewController;
import com.android.systemui.Dumpable;
+import com.android.systemui.biometrics.AuthController;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
@@ -165,6 +166,7 @@
private BiometricModeListener mBiometricModeListener;
private final MetricsLogger mMetricsLogger;
+ private final AuthController mAuthController;
private static final class PendingAuthenticated {
public final int userId;
@@ -254,7 +256,8 @@
PowerManager powerManager,
NotificationMediaManager notificationMediaManager,
WakefulnessLifecycle wakefulnessLifecycle,
- ScreenLifecycle screenLifecycle) {
+ ScreenLifecycle screenLifecycle,
+ AuthController authController) {
mContext = context;
mPowerManager = powerManager;
mShadeController = shadeController;
@@ -275,6 +278,7 @@
mKeyguardBypassController = keyguardBypassController;
mKeyguardBypassController.setUnlockController(this);
mMetricsLogger = metricsLogger;
+ mAuthController = authController;
dumpManager.registerDumpable(getClass().getName(), this);
}
@@ -588,14 +592,16 @@
return MODE_UNLOCK_COLLAPSING;
}
if (mKeyguardViewController.isShowing()) {
- if (mKeyguardViewController.bouncerIsOrWillBeShowing() && unlockingAllowed) {
+ if ((mKeyguardViewController.bouncerIsOrWillBeShowing()
+ || mKeyguardBypassController.getAltBouncerShowing()) && unlockingAllowed) {
if (bypass && mKeyguardBypassController.canPlaySubtleWindowAnimations()) {
return MODE_UNLOCK_FADING;
} else {
return MODE_DISMISS_BOUNCER;
}
} else if (unlockingAllowed) {
- return bypass ? MODE_UNLOCK_FADING : MODE_NONE;
+ return bypass || mAuthController.isUdfpsFingerDown()
+ ? MODE_UNLOCK_FADING : MODE_NONE;
} else {
return bypass ? MODE_SHOW_BOUNCER : MODE_NONE;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
index 26c6fe9..c9d0842 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
@@ -82,6 +82,7 @@
private set
var bouncerShowing: Boolean = false
+ var altBouncerShowing: Boolean = false
var launchingAffordance: Boolean = false
var qSExpanded = false
set(value) {
@@ -172,6 +173,7 @@
if (bypassEnabled) {
return when {
bouncerShowing -> true
+ altBouncerShowing -> true
statusBarStateController.state != StatusBarState.KEYGUARD -> false
launchingAffordance -> false
isPulseExpanding || qSExpanded -> false
@@ -210,6 +212,7 @@
pw.println(" bypassEnabled: $bypassEnabled")
pw.println(" canBypass: ${canBypass()}")
pw.println(" bouncerShowing: $bouncerShowing")
+ pw.println(" altBouncerShowing: $altBouncerShowing")
pw.println(" isPulseExpanding: $isPulseExpanding")
pw.println(" launchingAffordance: $launchingAffordance")
pw.println(" qSExpanded: $qSExpanded")
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
index 7f4dabd..b5d9bd6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
@@ -26,6 +26,7 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
+import android.util.Log;
import android.view.GestureDetector;
import android.view.InputDevice;
import android.view.KeyEvent;
@@ -66,6 +67,7 @@
* Controller for {@link NotificationShadeWindowView}.
*/
public class NotificationShadeWindowViewController {
+ private static final String TAG = "NotifShadeWindowVC";
private final InjectionInflationController mInjectionInflationController;
private final NotificationWakeUpCoordinator mCoordinator;
private final PulseExpansionHandler mPulseExpansionHandler;
@@ -213,6 +215,10 @@
mView.setInteractionEventHandler(new NotificationShadeWindowView.InteractionEventHandler() {
@Override
public Boolean handleDispatchTouchEvent(MotionEvent ev) {
+ if (mStatusBarView == null) {
+ Log.w(TAG, "Ignoring touch while statusBarView not yet set.");
+ return false;
+ }
boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN;
boolean isUp = ev.getActionMasked() == MotionEvent.ACTION_UP;
boolean isCancel = ev.getActionMasked() == MotionEvent.ACTION_CANCEL;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 0b6884b..6f63b17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -42,6 +42,8 @@
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardMessageArea;
+import com.android.keyguard.KeyguardMessageAreaController;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.KeyguardViewController;
@@ -50,6 +52,7 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.FaceAuthScreenBrightnessController;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.QuickStepContract;
@@ -80,7 +83,7 @@
public class StatusBarKeyguardViewManager implements RemoteInputController.Callback,
StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener,
PanelExpansionListener, NavigationModeController.ModeChangedListener,
- KeyguardViewController {
+ KeyguardViewController, WakefulnessLifecycle.Observer {
// When hiding the Keyguard with timing supplied from WindowManager, better be early than late.
private static final long HIDE_TIMING_CORRECTION_MS = - 16 * 3;
@@ -104,6 +107,10 @@
private final NotificationShadeWindowController mNotificationShadeWindowController;
private final Optional<FaceAuthScreenBrightnessController> mFaceAuthScreenBrightnessController;
private final KeyguardBouncer.Factory mKeyguardBouncerFactory;
+ private final WakefulnessLifecycle mWakefulnessLifecycle;
+ private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
+ private final KeyguardMessageAreaController.Factory mKeyguardMessageAreaFactory;
+ private KeyguardMessageAreaController mKeyguardMessageAreaController;
private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() {
@Override
public void onFullyShown() {
@@ -189,6 +196,7 @@
private boolean mLastPulsing;
private int mLastBiometricMode;
private boolean mQsExpanded;
+ private boolean mAnimatedToSleep;
private OnDismissAction mAfterKeyguardGoneAction;
private Runnable mKeyguardGoneCancelAction;
@@ -232,7 +240,10 @@
KeyguardStateController keyguardStateController,
Optional<FaceAuthScreenBrightnessController> faceAuthScreenBrightnessController,
NotificationMediaManager notificationMediaManager,
- KeyguardBouncer.Factory keyguardBouncerFactory) {
+ KeyguardBouncer.Factory keyguardBouncerFactory,
+ WakefulnessLifecycle wakefulnessLifecycle,
+ UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
+ KeyguardMessageAreaController.Factory keyguardMessageAreaFactory) {
mContext = context;
mViewMediatorCallback = callback;
mLockPatternUtils = lockPatternUtils;
@@ -246,6 +257,9 @@
mDockManager = dockManager;
mFaceAuthScreenBrightnessController = faceAuthScreenBrightnessController;
mKeyguardBouncerFactory = keyguardBouncerFactory;
+ mWakefulnessLifecycle = wakefulnessLifecycle;
+ mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
+ mKeyguardMessageAreaFactory = keyguardMessageAreaFactory;
}
@Override
@@ -263,6 +277,8 @@
notificationPanelViewController.addExpansionListener(this);
mBypassController = bypassController;
mNotificationContainer = notificationContainer;
+ mKeyguardMessageAreaController = mKeyguardMessageAreaFactory.create(
+ KeyguardMessageArea.findSecurityMessageDisplay(container));
mFaceAuthScreenBrightnessController.ifPresent((it) -> {
View overlay = new View(mContext);
container.addView(overlay);
@@ -301,6 +317,20 @@
mDockManager.addListener(mDockEventListener);
mIsDocked = mDockManager.isDocked();
}
+ mWakefulnessLifecycle.addObserver(new WakefulnessLifecycle.Observer() {
+ @Override
+ public void onFinishedWakingUp() {
+ mAnimatedToSleep = false;
+ updateStates();
+ }
+
+ @Override
+ public void onFinishedGoingToSleep() {
+ mAnimatedToSleep =
+ mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying();
+ updateStates();
+ }
+ });
}
@Override
@@ -390,9 +420,7 @@
*/
public void showGenericBouncer(boolean scrimmed) {
if (mAlternateAuthInterceptor != null) {
- if (mAlternateAuthInterceptor.showAlternateAuthBouncer()) {
- mStatusBar.updateScrimController();
- }
+ updateAlternateAuthShowing(mAlternateAuthInterceptor.showAlternateAuthBouncer());
return;
}
@@ -459,9 +487,7 @@
mKeyguardGoneCancelAction = null;
}
- if (mAlternateAuthInterceptor.showAlternateAuthBouncer()) {
- mStatusBar.updateScrimController();
- }
+ updateAlternateAuthShowing(mAlternateAuthInterceptor.showAlternateAuthBouncer());
return;
}
@@ -495,6 +521,7 @@
@Override
public void reset(boolean hideBouncerWhenShowing) {
if (mShowing) {
+ mNotificationPanelViewController.closeQs();
if (mOccluded && !mDozing) {
mStatusBar.hideKeyguard();
if (hideBouncerWhenShowing || mBouncer.needsFullscreenBouncer()) {
@@ -513,9 +540,19 @@
* Stop showing any alternate auth methods
*/
public void resetAlternateAuth(boolean forceUpdateScrim) {
- if ((mAlternateAuthInterceptor != null
+ final boolean updateScrim = (mAlternateAuthInterceptor != null
&& mAlternateAuthInterceptor.hideAlternateAuthBouncer())
- || forceUpdateScrim) {
+ || forceUpdateScrim;
+ updateAlternateAuthShowing(updateScrim);
+ }
+
+ private void updateAlternateAuthShowing(boolean updateScrim) {
+ if (mKeyguardMessageAreaController != null) {
+ mKeyguardMessageAreaController.setAltBouncerShowing(isShowingAlternateAuth());
+ }
+ mBypassController.setAltBouncerShowing(isShowingAlternateAuth());
+
+ if (updateScrim) {
mStatusBar.updateScrimController();
}
}
@@ -852,7 +889,7 @@
@Override
public boolean isBouncerShowing() {
- return mBouncer.isShowing();
+ return mBouncer.isShowing() || isShowingAlternateAuth();
}
@Override
@@ -981,7 +1018,7 @@
boolean hideWhileDozing = mDozing && biometricMode != MODE_WAKE_AND_UNLOCK_PULSING;
boolean keyguardWithGestureNav = (keyguardShowing && !mDozing || mPulsing && !mIsDocked)
&& mGesturalNav;
- return (!keyguardShowing && !hideWhileDozing || mBouncer.isShowing()
+ return (!mAnimatedToSleep && !keyguardShowing && !hideWhileDozing || mBouncer.isShowing()
|| mRemoteInputActive || keyguardWithGestureNav
|| mGlobalActionsVisible);
}
@@ -1066,7 +1103,14 @@
}
public void showBouncerMessage(String message, ColorStateList colorState) {
- mBouncer.showMessage(message, colorState);
+ if (isShowingAlternateAuth()) {
+ if (mKeyguardMessageAreaController != null) {
+ mKeyguardMessageAreaController.setNextMessageColor(colorState);
+ mKeyguardMessageAreaController.setMessage(message);
+ }
+ } else {
+ mBouncer.showMessage(message, colorState);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
index d7d1e73..acfdda4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.policy;
import android.hardware.SensorPrivacyManager.Sensors.Sensor;
+import android.hardware.SensorPrivacyManager.Sources.Source;
public interface IndividualSensorPrivacyController extends
CallbackController<IndividualSensorPrivacyController.Callback> {
@@ -26,7 +27,7 @@
boolean isSensorBlocked(@Sensor int sensor);
- void setSensorBlocked(@Sensor int sensor, boolean blocked);
+ void setSensorBlocked(@Source int source, @Sensor int sensor, boolean blocked);
void suppressSensorPrivacyReminders(String packageName, boolean suppress);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
index f58a7c0..9807165 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
@@ -21,6 +21,7 @@
import android.hardware.SensorPrivacyManager;
import android.hardware.SensorPrivacyManager.Sensors.Sensor;
+import android.hardware.SensorPrivacyManager.Sources.Source;
import android.util.ArraySet;
import android.util.SparseBooleanArray;
@@ -62,8 +63,8 @@
}
@Override
- public void setSensorBlocked(@Sensor int sensor, boolean blocked) {
- mSensorPrivacyManager.setSensorPrivacyForProfileGroup(sensor, blocked);
+ public void setSensorBlocked(@Source int source, @Sensor int sensor, boolean blocked) {
+ mSensorPrivacyManager.setSensorPrivacyForProfileGroup(source, sensor, blocked);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java
index fcdf702..5cd7810 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java
@@ -138,6 +138,31 @@
}
@Test
+ public void testStateUpdated_whenSwitchToFingerprint_invokesCallbacks() {
+ class TestModalityListener implements ModalityListener {
+ public int switchCount = 0;
+
+ @Override
+ public void onModalitySwitched(int oldModality, int newModality) {
+ assertEquals(TYPE_FINGERPRINT, newModality);
+ assertEquals(TYPE_FACE, oldModality);
+ switchCount++;
+ }
+ }
+ final TestModalityListener modalityListener = new TestModalityListener();
+
+ mFaceToFpView.onDialogAnimatedIn();
+ mFaceToFpView.setModalityListener(modalityListener);
+
+ assertEquals(0, modalityListener.switchCount);
+
+ mFaceToFpView.updateState(AuthBiometricFaceToFingerprintView.STATE_ERROR);
+ mFaceToFpView.updateState(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING);
+
+ assertEquals(1, modalityListener.switchCount);
+ }
+
+ @Test
public void testModeUpdated_onSoftError_whenSwitchToFingerprint() {
mFaceToFpView.onDialogAnimatedIn();
mFaceToFpView.onAuthenticationFailed(TYPE_FACE, "no face");
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index 9774ea9..bfcd131 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -59,6 +59,7 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
import android.testing.TestableLooper.RunWithLooper;
+import android.view.WindowManager;
import com.android.internal.R;
import com.android.systemui.SysuiTestCase;
@@ -97,6 +98,8 @@
@Mock
private ActivityTaskManager mActivityTaskManager;
@Mock
+ private WindowManager mWindowManager;
+ @Mock
private FingerprintManager mFingerprintManager;
@Mock
private FaceManager mFaceManager;
@@ -149,7 +152,7 @@
when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(props);
mAuthController = new TestableAuthController(context, mCommandQueue,
- mActivityTaskManager, mFingerprintManager, mFaceManager,
+ mActivityTaskManager, mWindowManager, mFingerprintManager, mFaceManager,
() -> mUdfpsController, () -> mSidefpsController);
mAuthController.start();
@@ -576,13 +579,15 @@
private int mBuildCount = 0;
private PromptInfo mLastBiometricPromptInfo;
- TestableAuthController(Context context, CommandQueue commandQueue,
+ TestableAuthController(Context context,
+ CommandQueue commandQueue,
ActivityTaskManager activityTaskManager,
+ WindowManager windowManager,
FingerprintManager fingerprintManager,
FaceManager faceManager,
Provider<UdfpsController> udfpsControllerFactory,
Provider<SidefpsController> sidefpsControllerFactory) {
- super(context, commandQueue, activityTaskManager,
+ super(context, commandQueue, activityTaskManager, windowManager,
fingerprintManager, faceManager, udfpsControllerFactory,
sidefpsControllerFactory);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index b54f923..60f0b68 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -40,6 +40,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.biometrics.AuthController;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
@@ -89,6 +90,8 @@
@Mock
private KeyguardBypassController mKeyguardBypassController;
@Mock
+ private AuthController mAuthController;
+ @Mock
private DozeParameters mDozeParameters;
@Mock
private MetricsLogger mMetricsLogger;
@@ -109,6 +112,7 @@
when(mKeyguardStateController.isFaceAuthEnabled()).thenReturn(true);
when(mKeyguardBypassController.onBiometricAuthenticated(any(), anyBoolean()))
.thenReturn(true);
+ when(mAuthController.isUdfpsFingerDown()).thenReturn(false);
when(mKeyguardBypassController.canPlaySubtleWindowAnimations()).thenReturn(true);
mContext.addMockSystemService(PowerManager.class, mPowerManager);
mDependency.injectTestDependency(NotificationMediaManager.class, mMediaManager);
@@ -118,7 +122,8 @@
mNotificationShadeWindowController, mKeyguardStateController, mHandler,
mUpdateMonitor, res.getResources(), mKeyguardBypassController, mDozeParameters,
mMetricsLogger, mDumpManager, mPowerManager,
- mNotificationMediaManager, mWakefulnessLifecycle, mScreenLifecycle);
+ mNotificationMediaManager, mWakefulnessLifecycle, mScreenLifecycle,
+ mAuthController);
mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
mBiometricUnlockController.setBiometricModeListener(mBiometricModeListener);
}
@@ -229,6 +234,25 @@
}
@Test
+ public void onBiometricAuthenticated_whenFace_andNonBypassAndUdfps_dismissKeyguard() {
+ when(mKeyguardBypassController.getBypassEnabled()).thenReturn(false);
+ when(mAuthController.isUdfpsFingerDown()).thenReturn(true);
+ mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
+
+ when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
+ // the value of isStrongBiometric doesn't matter here since we only care about the returned
+ // value of isUnlockingWithBiometricAllowed()
+ mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
+ BiometricSourceType.FACE, true /* isStrongBiometric */);
+
+ verify(mShadeController, never()).animateCollapsePanels(anyInt(), anyBoolean(),
+ anyBoolean(), anyFloat());
+ verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false));
+ assertThat(mBiometricUnlockController.getMode())
+ .isEqualTo(BiometricUnlockController.MODE_UNLOCK_FADING);
+ }
+
+ @Test
public void onBiometricAuthenticated_whenFace_andBypass_encrypted_showBouncer() {
reset(mUpdateMonitor);
when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 1d4cbdc..c39a906 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -16,11 +16,15 @@
package com.android.systemui.statusbar.phone;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
+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 static org.mockito.Mockito.reset;
@@ -35,12 +39,15 @@
import androidx.test.filters.SmallTest;
import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardMessageArea;
+import com.android.keyguard.KeyguardMessageAreaController;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.FaceAuthScreenBrightnessController;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -89,8 +96,15 @@
@Mock
private KeyguardBouncer.Factory mKeyguardBouncerFactory;
@Mock
+ private KeyguardMessageAreaController.Factory mKeyguardMessageAreaFactory;
+ @Mock
private KeyguardBouncer mBouncer;
+ @Mock
+ private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
+ @Mock
+ private KeyguardMessageArea mKeyguardMessageArea;
+ private WakefulnessLifecycle mWakefulnessLifecycle;
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Before
@@ -101,6 +115,8 @@
any(KeyguardBouncer.BouncerExpansionCallback.class)))
.thenReturn(mBouncer);
+ when(mContainer.findViewById(anyInt())).thenReturn(mKeyguardMessageArea);
+ mWakefulnessLifecycle = new WakefulnessLifecycle(getContext(), null);
mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(
getContext(),
mViewMediatorCallback,
@@ -114,7 +130,10 @@
mKeyguardStateController,
Optional.of(mFaceAuthScreenBrightnessController),
mock(NotificationMediaManager.class),
- mKeyguardBouncerFactory);
+ mKeyguardBouncerFactory,
+ mWakefulnessLifecycle,
+ mUnlockedScreenOffAnimationController,
+ mKeyguardMessageAreaFactory);
mStatusBarKeyguardViewManager.registerStatusBar(mStatusBar, mContainer,
mNotificationPanelView, mBiometrucUnlockController,
mNotificationContainer, mBypassController);
@@ -280,4 +299,18 @@
verify(mBouncer).updateKeyguardPosition(1.0f);
}
+
+ @Test
+ public void testNavBarHiddenWhenSleepAnimationStarts() {
+ mStatusBarKeyguardViewManager.hide(0 /* startTime */, 0 /* fadeoutDuration */);
+ assertTrue(mStatusBarKeyguardViewManager.isNavBarVisible());
+
+ // Verify that the nav bar is hidden when the screen off animation starts
+ doReturn(true).when(mUnlockedScreenOffAnimationController).isScreenOffAnimationPlaying();
+ mWakefulnessLifecycle.dispatchFinishedGoingToSleep();
+ assertFalse(mStatusBarKeyguardViewManager.isNavBarVisible());
+
+ mWakefulnessLifecycle.dispatchFinishedWakingUp();
+ assertTrue(mStatusBarKeyguardViewManager.isNavBarVisible());
+ }
}
diff --git a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
index ab3643c..561d079 100644
--- a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
+++ b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
@@ -134,6 +134,7 @@
(!EXTENSIONS_VERSION.startsWith(NON_INIT_VERSION_PREFIX));
private HashMap<String, CameraCharacteristics> mCharacteristicsHashMap = new HashMap<>();
+ private HashMap<String, Long> mMetadataVendorIdMap = new HashMap<>();
private static boolean checkForAdvancedAPI() {
if (EXTENSIONS_PRESENT && EXTENSIONS_VERSION.startsWith(ADVANCED_VERSION_PREFIX)) {
@@ -464,8 +465,16 @@
String [] cameraIds = manager.getCameraIdListNoLazy();
if (cameraIds != null) {
for (String cameraId : cameraIds) {
- mCharacteristicsHashMap.put(cameraId,
- manager.getCameraCharacteristics(cameraId));
+ CameraCharacteristics chars = manager.getCameraCharacteristics(cameraId);
+ mCharacteristicsHashMap.put(cameraId, chars);
+ Object thisClass = CameraCharacteristics.Key.class;
+ Class<CameraCharacteristics.Key<?>> keyClass =
+ (Class<CameraCharacteristics.Key<?>>)thisClass;
+ ArrayList<CameraCharacteristics.Key<?>> vendorKeys =
+ chars.getNativeMetadata().getAllVendorKeys(keyClass);
+ if ((vendorKeys != null) && !vendorKeys.isEmpty()) {
+ mMetadataVendorIdMap.put(cameraId, vendorKeys.get(0).getVendorId());
+ }
}
}
} catch (CameraAccessException e) {
@@ -529,13 +538,16 @@
return ret;
}
- private static CameraMetadataNative initializeParcelableMetadata(
- List<Pair<CaptureRequest.Key, Object>> paramList) {
+ private CameraMetadataNative initializeParcelableMetadata(
+ List<Pair<CaptureRequest.Key, Object>> paramList, String cameraId) {
if (paramList == null) {
return null;
}
CameraMetadataNative ret = new CameraMetadataNative();
+ if (mMetadataVendorIdMap.containsKey(cameraId)) {
+ ret.setVendorId(mMetadataVendorIdMap.get(cameraId));
+ }
for (Pair<CaptureRequest.Key, Object> param : paramList) {
ret.set(param.first, param.second);
}
@@ -543,13 +555,16 @@
return ret;
}
- private static CameraMetadataNative initializeParcelableMetadata(
- Map<CaptureRequest.Key<?>, Object> paramMap) {
+ private CameraMetadataNative initializeParcelableMetadata(
+ Map<CaptureRequest.Key<?>, Object> paramMap, String cameraId) {
if (paramMap == null) {
return null;
}
CameraMetadataNative ret = new CameraMetadataNative();
+ if (mMetadataVendorIdMap.containsKey(cameraId)) {
+ ret.setVendorId(mMetadataVendorIdMap.get(cameraId));
+ }
for (Map.Entry<CaptureRequest.Key<?>, Object> param : paramMap.entrySet()) {
ret.set(((CaptureRequest.Key) param.getKey()), param.getValue());
}
@@ -557,8 +572,8 @@
return ret;
}
- private static android.hardware.camera2.extension.CaptureStageImpl initializeParcelable(
- androidx.camera.extensions.impl.CaptureStageImpl captureStage) {
+ private android.hardware.camera2.extension.CaptureStageImpl initializeParcelable(
+ androidx.camera.extensions.impl.CaptureStageImpl captureStage, String cameraId) {
if (captureStage == null) {
return null;
}
@@ -566,12 +581,13 @@
android.hardware.camera2.extension.CaptureStageImpl ret =
new android.hardware.camera2.extension.CaptureStageImpl();
ret.id = captureStage.getId();
- ret.parameters = initializeParcelableMetadata(captureStage.getParameters());
+ ret.parameters = initializeParcelableMetadata(captureStage.getParameters(), cameraId);
return ret;
}
- private Request initializeParcelable(RequestProcessorImpl.Request request, int requestId) {
+ private Request initializeParcelable(RequestProcessorImpl.Request request, int requestId,
+ String cameraId) {
Request ret = new Request();
ret.targetOutputConfigIds = new ArrayList<>();
for (int id : request.getTargetOutputConfigIds()) {
@@ -580,7 +596,7 @@
ret.targetOutputConfigIds.add(configId);
}
ret.templateId = request.getTemplateId();
- ret.parameters = initializeParcelableMetadata(request.getParameters());
+ ret.parameters = initializeParcelableMetadata(request.getParameters(), cameraId);
ret.requestId = requestId;
return ret;
}
@@ -933,9 +949,11 @@
private class RequestProcessorStub implements RequestProcessorImpl {
private final IRequestProcessorImpl mRequestProcessor;
+ private final String mCameraId;
- public RequestProcessorStub(IRequestProcessorImpl requestProcessor) {
+ public RequestProcessorStub(IRequestProcessorImpl requestProcessor, String cameraId) {
mRequestProcessor = requestProcessor;
+ mCameraId = cameraId;
}
@Override
@@ -964,7 +982,7 @@
new ArrayList<>();
int requestId = 0;
for (Request request : requests) {
- captureRequests.add(initializeParcelable(request, requestId));
+ captureRequests.add(initializeParcelable(request, requestId, mCameraId));
requestId++;
}
@@ -982,7 +1000,8 @@
try {
ArrayList<Request> requests = new ArrayList<>();
requests.add(request);
- return mRequestProcessor.setRepeating(initializeParcelable(request, 0),
+ return mRequestProcessor.setRepeating(
+ initializeParcelable(request, 0, mCameraId),
new RequestCallbackStub(requests, callback));
} catch (RemoteException e) {
Log.e(TAG, "Failed to submit repeating request due to remote exception!");
@@ -1012,6 +1031,7 @@
private class SessionProcessorImplStub extends ISessionProcessorImpl.Stub {
private final SessionProcessorImpl mSessionProcessor;
+ private String mCameraId = null;
public SessionProcessorImplStub(SessionProcessorImpl sessionProcessor) {
mSessionProcessor = sessionProcessor;
@@ -1074,7 +1094,8 @@
}
ret.sessionTemplateId = sessionConfig.getSessionTemplateId();
ret.sessionParameter = initializeParcelableMetadata(
- sessionConfig.getSessionParameters());
+ sessionConfig.getSessionParameters(), cameraId);
+ mCameraId = cameraId;
return ret;
}
@@ -1086,7 +1107,8 @@
@Override
public void onCaptureSessionStart(IRequestProcessorImpl requestProcessor) {
- mSessionProcessor.onCaptureSessionStart(new RequestProcessorStub(requestProcessor));
+ mSessionProcessor.onCaptureSessionStart(
+ new RequestProcessorStub(requestProcessor, mCameraId));
}
@Override
@@ -1143,6 +1165,7 @@
private class PreviewExtenderImplStub extends IPreviewExtenderImpl.Stub {
private final PreviewExtenderImpl mPreviewExtender;
+ private String mCameraId = null;
public PreviewExtenderImplStub(PreviewExtenderImpl previewExtender) {
mPreviewExtender = previewExtender;
@@ -1150,6 +1173,7 @@
@Override
public void onInit(String cameraId, CameraMetadataNative cameraCharacteristics) {
+ mCameraId = cameraId;
mPreviewExtender.onInit(cameraId, new CameraCharacteristics(cameraCharacteristics),
CameraExtensionsProxyService.this);
}
@@ -1161,17 +1185,17 @@
@Override
public CaptureStageImpl onPresetSession() {
- return initializeParcelable(mPreviewExtender.onPresetSession());
+ return initializeParcelable(mPreviewExtender.onPresetSession(), mCameraId);
}
@Override
public CaptureStageImpl onEnableSession() {
- return initializeParcelable(mPreviewExtender.onEnableSession());
+ return initializeParcelable(mPreviewExtender.onEnableSession(), mCameraId);
}
@Override
public CaptureStageImpl onDisableSession() {
- return initializeParcelable(mPreviewExtender.onDisableSession());
+ return initializeParcelable(mPreviewExtender.onDisableSession(), mCameraId);
}
@Override
@@ -1187,7 +1211,7 @@
@Override
public CaptureStageImpl getCaptureStage() {
- return initializeParcelable(mPreviewExtender.getCaptureStage());
+ return initializeParcelable(mPreviewExtender.getCaptureStage(), mCameraId);
}
@Override
@@ -1230,7 +1254,7 @@
}
if (processor != null) {
- return new RequestUpdateProcessorImplStub(processor);
+ return new RequestUpdateProcessorImplStub(processor, mCameraId);
}
return null;
@@ -1251,6 +1275,7 @@
private class ImageCaptureExtenderImplStub extends IImageCaptureExtenderImpl.Stub {
private final ImageCaptureExtenderImpl mImageExtender;
+ private String mCameraId = null;
public ImageCaptureExtenderImplStub(ImageCaptureExtenderImpl imageExtender) {
mImageExtender = imageExtender;
@@ -1260,6 +1285,7 @@
public void onInit(String cameraId, CameraMetadataNative cameraCharacteristics) {
mImageExtender.onInit(cameraId, new CameraCharacteristics(cameraCharacteristics),
CameraExtensionsProxyService.this);
+ mCameraId = cameraId;
}
@Override
@@ -1269,17 +1295,17 @@
@Override
public CaptureStageImpl onPresetSession() {
- return initializeParcelable(mImageExtender.onPresetSession());
+ return initializeParcelable(mImageExtender.onPresetSession(), mCameraId);
}
@Override
public CaptureStageImpl onEnableSession() {
- return initializeParcelable(mImageExtender.onEnableSession());
+ return initializeParcelable(mImageExtender.onEnableSession(), mCameraId);
}
@Override
public CaptureStageImpl onDisableSession() {
- return initializeParcelable(mImageExtender.onDisableSession());
+ return initializeParcelable(mImageExtender.onDisableSession(), mCameraId);
}
@Override
@@ -1312,7 +1338,7 @@
ArrayList<android.hardware.camera2.extension.CaptureStageImpl> ret =
new ArrayList<>();
for (androidx.camera.extensions.impl.CaptureStageImpl stage : captureStages) {
- ret.add(initializeParcelable(stage));
+ ret.add(initializeParcelable(stage, mCameraId));
}
return ret;
@@ -1428,9 +1454,12 @@
private class RequestUpdateProcessorImplStub extends IRequestUpdateProcessorImpl.Stub {
private final RequestUpdateProcessorImpl mProcessor;
+ private final String mCameraId;
- public RequestUpdateProcessorImplStub(RequestUpdateProcessorImpl processor) {
+ public RequestUpdateProcessorImplStub(RequestUpdateProcessorImpl processor,
+ String cameraId) {
mProcessor = processor;
+ mCameraId = cameraId;
}
@Override
@@ -1451,7 +1480,7 @@
@Override
public CaptureStageImpl process(CameraMetadataNative result, int sequenceId) {
return initializeParcelable(
- mProcessor.process(new TotalCaptureResult(result, sequenceId)));
+ mProcessor.process(new TotalCaptureResult(result, sequenceId)), mCameraId);
}
}
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index f7ddd29..95186ee 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -566,6 +566,12 @@
public abstract ProviderInfo resolveContentProvider(String name, int flags, int userId);
/**
+ * Resolves a content provider intent.
+ */
+ public abstract ProviderInfo resolveContentProvider(String name, int flags, int userId,
+ int callingUid);
+
+ /**
* Track the creator of a new isolated uid.
* @param isolatedUid The newly created isolated uid.
* @param ownerUid The uid of the app that created the isolated process.
diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java
index 51ad23c..53ff8ff7 100644
--- a/services/core/java/com/android/server/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/SensorPrivacyService.java
@@ -36,9 +36,26 @@
import static android.hardware.SensorPrivacyManager.EXTRA_SENSOR;
import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
+import static android.hardware.SensorPrivacyManager.Sources.DIALOG;
+import static android.hardware.SensorPrivacyManager.Sources.OTHER;
+import static android.hardware.SensorPrivacyManager.Sources.QS_TILE;
+import static android.hardware.SensorPrivacyManager.Sources.SETTINGS;
+import static android.hardware.SensorPrivacyManager.Sources.SHELL;
import static android.os.UserHandle.USER_SYSTEM;
import static android.service.SensorPrivacyIndividualEnabledSensorProto.UNKNOWN;
+import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION;
+import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__ACTION__TOGGLE_OFF;
+import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__ACTION__TOGGLE_ON;
+import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__SENSOR__CAMERA;
+import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__SENSOR__MICROPHONE;
+import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__SENSOR__SENSOR_UNKNOWN;
+import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__SOURCE__DIALOG;
+import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__SOURCE__QS_TILE;
+import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__SOURCE__SETTINGS;
+import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION__SOURCE__SOURCE_UNKNOWN;
+import static com.android.internal.util.FrameworkStatsLog.write;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -77,6 +94,7 @@
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.ShellCommand;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -130,6 +148,8 @@
public final class SensorPrivacyService extends SystemService {
private static final String TAG = SensorPrivacyService.class.getSimpleName();
+ private static final boolean DEBUG = false;
+ private static final boolean DEBUG_LOGGING = false;
/** Version number indicating compatibility parsing the persisted file */
private static final int CURRENT_PERSISTENCE_VERSION = 1;
@@ -145,6 +165,7 @@
private static final String XML_ATTRIBUTE_PERSISTENCE_VERSION = "persistence-version";
private static final String XML_ATTRIBUTE_VERSION = "version";
private static final String XML_ATTRIBUTE_ENABLED = "enabled";
+ private static final String XML_ATTRIBUTE_LAST_CHANGE = "last-change";
private static final String XML_ATTRIBUTE_SENSOR = "sensor";
private static final String SENSOR_PRIVACY_CHANNEL_ID = Context.SENSOR_PRIVACY_SERVICE;
@@ -231,7 +252,7 @@
@GuardedBy("mLock")
private SparseBooleanArray mEnabled = new SparseBooleanArray();
@GuardedBy("mLock")
- private SparseArray<SparseBooleanArray> mIndividualEnabled = new SparseArray<>();
+ private SparseArray<SparseArray<SensorState>> mIndividualEnabled = new SparseArray<>();
/**
* Packages for which not to show sensor use reminders.
@@ -245,6 +266,34 @@
private final ArrayMap<SensorUseReminderDialogInfo, ArraySet<Integer>>
mQueuedSensorUseReminderDialogs = new ArrayMap<>();
+ private class SensorState {
+ private boolean mEnabled;
+ private long mLastChange;
+
+ SensorState(boolean enabled) {
+ mEnabled = enabled;
+ mLastChange = getCurrentTimeMillis();
+ }
+
+ SensorState(boolean enabled, long lastChange) {
+ mEnabled = enabled;
+ if (lastChange < 0) {
+ mLastChange = getCurrentTimeMillis();
+ } else {
+ mLastChange = lastChange;
+ }
+ }
+
+ boolean setEnabled(boolean enabled) {
+ if (mEnabled != enabled) {
+ mEnabled = enabled;
+ mLastChange = getCurrentTimeMillis();
+ return true;
+ }
+ return false;
+ }
+ }
+
private class SensorUseReminderDialogInfo {
private int mTaskId;
private UserHandle mUser;
@@ -288,12 +337,14 @@
mAppOpsManager.startWatchingNoted(micAndCameraOps, this);
mAppOpsManager.startWatchingStarted(micAndCameraOps, this);
+
+
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
setIndividualSensorPrivacy(
((UserHandle) intent.getParcelableExtra(
- Intent.EXTRA_USER)).getIdentifier(),
+ Intent.EXTRA_USER)).getIdentifier(), OTHER,
intent.getIntExtra(EXTRA_SENSOR, UNKNOWN), false);
}
}, new IntentFilter(ACTION_DISABLE_INDIVIDUAL_SENSOR_PRIVACY),
@@ -307,11 +358,11 @@
// Reset sensor privacy when restriction is added
if (!prevRestrictions.getBoolean(UserManager.DISALLOW_CAMERA_TOGGLE)
&& newRestrictions.getBoolean(UserManager.DISALLOW_CAMERA_TOGGLE)) {
- setIndividualSensorPrivacyUnchecked(userId, CAMERA, false);
+ setIndividualSensorPrivacyUnchecked(userId, OTHER, CAMERA, false);
}
if (!prevRestrictions.getBoolean(UserManager.DISALLOW_MICROPHONE_TOGGLE)
&& newRestrictions.getBoolean(UserManager.DISALLOW_MICROPHONE_TOGGLE)) {
- setIndividualSensorPrivacyUnchecked(userId, MICROPHONE, false);
+ setIndividualSensorPrivacyUnchecked(userId, OTHER, MICROPHONE, false);
}
}
@@ -645,22 +696,40 @@
}
@Override
- public void setIndividualSensorPrivacy(@UserIdInt int userId, int sensor, boolean enable) {
+ public void setIndividualSensorPrivacy(@UserIdInt int userId,
+ @SensorPrivacyManager.Sources.Source int source, int sensor, boolean enable) {
enforceManageSensorPrivacyPermission();
if (!canChangeIndividualSensorPrivacy(userId, sensor)) {
return;
}
- setIndividualSensorPrivacyUnchecked(userId, sensor, enable);
+ setIndividualSensorPrivacyUnchecked(userId, source, sensor, enable);
}
- private void setIndividualSensorPrivacyUnchecked(int userId, int sensor, boolean enable) {
+ private void setIndividualSensorPrivacyUnchecked(int userId, int source, int sensor,
+ boolean enable) {
synchronized (mLock) {
- SparseBooleanArray userIndividualEnabled = mIndividualEnabled.get(userId,
- new SparseBooleanArray());
- userIndividualEnabled.put(sensor, enable);
+ SparseArray<SensorState> userIndividualEnabled = mIndividualEnabled.get(userId,
+ new SparseArray<>());
+ SensorState sensorState = userIndividualEnabled.get(sensor);
+ long lastChange;
+ if (sensorState != null) {
+ lastChange = sensorState.mLastChange;
+ if (!sensorState.setEnabled(enable)) {
+ // State not changing
+ return;
+ }
+ } else {
+ sensorState = new SensorState(enable);
+ lastChange = sensorState.mLastChange;
+ userIndividualEnabled.put(sensor, sensorState);
+ }
mIndividualEnabled.put(userId, userIndividualEnabled);
+ if (userId == mUserManagerInternal.getProfileParentId(userId)) {
+ logSensorPrivacyToggle(source, sensor, sensorState.mEnabled, lastChange);
+ }
+
if (!enable) {
long token = Binder.clearCallingIdentity();
try {
@@ -704,14 +773,61 @@
return true;
}
+ private void logSensorPrivacyToggle(int source, int sensor, boolean enabled,
+ long lastChange) {
+ long logMins = Math.max(0, (getCurrentTimeMillis() - lastChange) / (1000 * 60));
+
+ int logAction = -1;
+ if (enabled) {
+ logAction = PRIVACY_SENSOR_TOGGLE_INTERACTION__ACTION__TOGGLE_OFF;
+ } else {
+ logAction = PRIVACY_SENSOR_TOGGLE_INTERACTION__ACTION__TOGGLE_ON;
+ }
+
+ int logSensor = -1;
+ switch(sensor) {
+ case CAMERA:
+ logSensor = PRIVACY_SENSOR_TOGGLE_INTERACTION__SENSOR__CAMERA;
+ break;
+ case MICROPHONE:
+ logSensor = PRIVACY_SENSOR_TOGGLE_INTERACTION__SENSOR__MICROPHONE;
+ break;
+ default:
+ logSensor = PRIVACY_SENSOR_TOGGLE_INTERACTION__SENSOR__SENSOR_UNKNOWN;
+ }
+
+ int logSource = -1;
+ switch(source) {
+ case QS_TILE :
+ logSource = PRIVACY_SENSOR_TOGGLE_INTERACTION__SOURCE__QS_TILE;
+ break;
+ case DIALOG :
+ logSource = PRIVACY_SENSOR_TOGGLE_INTERACTION__SOURCE__DIALOG;
+ break;
+ case SETTINGS:
+ logSource = PRIVACY_SENSOR_TOGGLE_INTERACTION__SOURCE__SETTINGS;
+ break;
+ default:
+ logSource = PRIVACY_SENSOR_TOGGLE_INTERACTION__SOURCE__SOURCE_UNKNOWN;
+ }
+
+ if (DEBUG || DEBUG_LOGGING) {
+ Log.d(TAG, "Logging sensor toggle interaction:" + " logSensor=" + logSensor
+ + " logAction=" + logAction + " logSource=" + logSource + " logMins="
+ + logMins);
+ }
+ write(PRIVACY_SENSOR_TOGGLE_INTERACTION, logSensor, logAction, logSource, logMins);
+
+ }
+
@Override
- public void setIndividualSensorPrivacyForProfileGroup(@UserIdInt int userId, int sensor,
- boolean enable) {
+ public void setIndividualSensorPrivacyForProfileGroup(@UserIdInt int userId,
+ @SensorPrivacyManager.Sources.Source int source, int sensor, boolean enable) {
enforceManageSensorPrivacyPermission();
int parentId = mUserManagerInternal.getProfileParentId(userId);
forAllUsers(userId2 -> {
if (parentId == mUserManagerInternal.getProfileParentId(userId2)) {
- setIndividualSensorPrivacy(userId2, sensor, enable);
+ setIndividualSensorPrivacy(userId2, source, sensor, enable);
}
});
}
@@ -762,11 +878,15 @@
public boolean isIndividualSensorPrivacyEnabled(@UserIdInt int userId, int sensor) {
enforceObserveSensorPrivacyPermission();
synchronized (mLock) {
- SparseBooleanArray states = mIndividualEnabled.get(userId);
+ SparseArray<SensorState> states = mIndividualEnabled.get(userId);
if (states == null) {
return false;
}
- return states.get(sensor, false);
+ SensorState state = states.get(sensor);
+ if (state == null) {
+ return false;
+ }
+ return state.mEnabled;
}
}
@@ -791,7 +911,7 @@
// these should never be changed even with refactorings.
if (persistenceVersion == 0) {
boolean enabled = parser.getAttributeBoolean(null, "enabled", false);
- SparseBooleanArray individualEnabled = new SparseBooleanArray();
+ SparseArray<SensorState> individualEnabled = new SparseArray<>();
version = 0;
XmlUtils.nextElement(parser);
@@ -801,7 +921,7 @@
int sensor = XmlUtils.readIntAttribute(parser, "sensor");
boolean indEnabled = XmlUtils.readBooleanAttribute(parser,
"enabled");
- individualEnabled.put(sensor, indEnabled);
+ individualEnabled.put(sensor, new SensorState(indEnabled));
XmlUtils.skipCurrentTag(parser);
} else {
XmlUtils.nextElement(parser);
@@ -811,7 +931,8 @@
map.put(VER0_INDIVIDUAL_ENABLED, individualEnabled);
} else if (persistenceVersion == CURRENT_PERSISTENCE_VERSION) {
SparseBooleanArray enabled = new SparseBooleanArray();
- SparseArray<SparseBooleanArray> individualEnabled = new SparseArray<>();
+ SparseArray<SparseArray<SensorState>> individualEnabled =
+ new SparseArray<>();
version = parser.getAttributeInt(null,
XML_ATTRIBUTE_VERSION, 1);
@@ -847,10 +968,13 @@
int sensor = parser.getAttributeInt(null, XML_ATTRIBUTE_SENSOR);
boolean isEnabled = parser.getAttributeBoolean(null,
XML_ATTRIBUTE_ENABLED);
- SparseBooleanArray userIndividualEnabled = individualEnabled.get(
- currentUserId, new SparseBooleanArray());
+ long lastChange = parser
+ .getAttributeLong(null, XML_ATTRIBUTE_LAST_CHANGE, -1);
+ SparseArray<SensorState> userIndividualEnabled =
+ individualEnabled.get(currentUserId, new SparseArray<>());
- userIndividualEnabled.put(sensor, isEnabled);
+ userIndividualEnabled
+ .put(sensor, new SensorState(isEnabled, lastChange));
individualEnabled.put(currentUserId, userIndividualEnabled);
}
}
@@ -883,7 +1007,7 @@
mEnabled = new SparseBooleanArray();
mIndividualEnabled = new SparseArray<>();
forAllUsers(userId -> mEnabled.put(userId, false));
- forAllUsers(userId -> mIndividualEnabled.put(userId, new SparseBooleanArray()));
+ forAllUsers(userId -> mIndividualEnabled.put(userId, new SparseArray<>()));
return true;
}
boolean upgraded = false;
@@ -920,7 +1044,7 @@
if (version == CURRENT_VERSION) {
mEnabled = (SparseBooleanArray) map.get(VER1_ENABLED);
mIndividualEnabled =
- (SparseArray<SparseBooleanArray>) map.get(VER1_INDIVIDUAL_ENABLED);
+ (SparseArray<SparseArray<SensorState>>) map.get(VER1_INDIVIDUAL_ENABLED);
}
return upgraded;
}
@@ -950,15 +1074,18 @@
serializer.attributeBoolean(
null, XML_ATTRIBUTE_ENABLED, isSensorPrivacyEnabled(userId));
- SparseBooleanArray individualEnabled =
- mIndividualEnabled.get(userId, new SparseBooleanArray());
+ SparseArray<SensorState> individualEnabled =
+ mIndividualEnabled.get(userId, new SparseArray<>());
int numIndividual = individualEnabled.size();
for (int i = 0; i < numIndividual; i++) {
serializer.startTag(null, XML_TAG_INDIVIDUAL_SENSOR_PRIVACY);
int sensor = individualEnabled.keyAt(i);
- boolean enabled = individualEnabled.valueAt(i);
+ SensorState sensorState = individualEnabled.valueAt(i);
+ boolean enabled = sensorState.mEnabled;
+ long lastChange = sensorState.mLastChange;
serializer.attributeInt(null, XML_ATTRIBUTE_SENSOR, sensor);
serializer.attributeBoolean(null, XML_ATTRIBUTE_ENABLED, enabled);
+ serializer.attributeLong(null, XML_ATTRIBUTE_LAST_CHANGE, lastChange);
serializer.endTag(null, XML_TAG_INDIVIDUAL_SENSOR_PRIVACY);
}
serializer.endTag(null, XML_TAG_USER);
@@ -1163,7 +1290,7 @@
dumpStream.write("is_enabled", SensorPrivacyUserProto.IS_ENABLED,
mEnabled.get(userId, false));
- SparseBooleanArray individualEnabled = mIndividualEnabled.get(userId);
+ SparseArray<SensorState> individualEnabled = mIndividualEnabled.get(userId);
if (individualEnabled != null) {
int numIndividualEnabled = individualEnabled.size();
for (int i = 0; i < numIndividualEnabled; i++) {
@@ -1175,7 +1302,8 @@
individualEnabled.keyAt(i));
dumpStream.write("is_enabled",
SensorPrivacyIndividualEnabledSensorProto.IS_ENABLED,
- individualEnabled.valueAt(i));
+ individualEnabled.valueAt(i).mEnabled);
+ // TODO dump last change
dumpStream.end(individualToken);
}
@@ -1232,7 +1360,7 @@
return -1;
}
- setIndividualSensorPrivacy(userId, sensor, true);
+ setIndividualSensorPrivacy(userId, SHELL, sensor, true);
}
break;
case "disable" : {
@@ -1242,7 +1370,7 @@
return -1;
}
- setIndividualSensorPrivacy(userId, sensor, false);
+ setIndividualSensorPrivacy(userId, SHELL, sensor, false);
}
break;
case "reset": {
@@ -1255,7 +1383,7 @@
enforceManageSensorPrivacyPermission();
synchronized (mLock) {
- SparseBooleanArray individualEnabled =
+ SparseArray<SensorState> individualEnabled =
mIndividualEnabled.get(userId);
if (individualEnabled != null) {
individualEnabled.delete(sensor);
@@ -1616,7 +1744,7 @@
if (mSensorPrivacyServiceImpl
.isIndividualSensorPrivacyEnabled(getCurrentUser(), MICROPHONE)) {
mSensorPrivacyServiceImpl.setIndividualSensorPrivacyUnchecked(
- getCurrentUser(), MICROPHONE, false);
+ getCurrentUser(), OTHER, MICROPHONE, false);
mMicUnmutedForEmergencyCall = true;
} else {
mMicUnmutedForEmergencyCall = false;
@@ -1631,11 +1759,19 @@
mIsInEmergencyCall = false;
if (mMicUnmutedForEmergencyCall) {
mSensorPrivacyServiceImpl.setIndividualSensorPrivacyUnchecked(
- getCurrentUser(), MICROPHONE, true);
+ getCurrentUser(), OTHER, MICROPHONE, true);
mMicUnmutedForEmergencyCall = false;
}
}
}
}
}
+
+ private static long getCurrentTimeMillis() {
+ try {
+ return SystemClock.currentNetworkTimeMillis();
+ } catch (Exception e) {
+ return System.currentTimeMillis();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 530f918..ccdc3f8 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -489,7 +489,7 @@
volatile long mFgsStartForegroundTimeoutMs = DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS;
/**
- * Sample rate for the FGS westworld atom.
+ * Sample rate for the FGS atom.
*
* If the value is 0.1, 10% of the installed packages would be sampled.
*/
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 5cb6fd9..d6bf8db 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1574,8 +1574,9 @@
state.setSystemNoUi(false);
}
if (!state.isSystemNoUi()) {
- if (mService.mWakefulness.get() == PowerManagerInternal.WAKEFULNESS_AWAKE) {
- // screen on, promote UI
+ if (mService.mWakefulness.get() == PowerManagerInternal.WAKEFULNESS_AWAKE
+ || state.isRunningRemoteAnimation()) {
+ // screen on or animating, promote UI
state.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI);
state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
} else {
diff --git a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
index ea0107e..26a6312 100644
--- a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
@@ -594,6 +594,7 @@
private final int mSession;
private final int mSource;
private final String mPackName;
+ private final boolean mSilenced;
RecordingEvent(int event, int riid, AudioRecordingConfiguration config) {
mRecEvent = event;
@@ -603,11 +604,13 @@
mSession = config.getClientAudioSessionId();
mSource = config.getClientAudioSource();
mPackName = config.getClientPackageName();
+ mSilenced = config.isClientSilenced();
} else {
mClientUid = -1;
mSession = -1;
mSource = -1;
mPackName = null;
+ mSilenced = false;
}
}
@@ -633,6 +636,7 @@
.append(" uid:").append(mClientUid)
.append(" session:").append(mSession)
.append(" src:").append(MediaRecorder.toLogFriendlyAudioSource(mSource))
+ .append(mSilenced ? " silenced" : " not silenced")
.append(mPackName == null ? "" : " pack:" + mPackName).toString();
}
}
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 1a07cb8..a4a5f96 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -68,6 +68,7 @@
private static final int MSG_INVALIDATE_SHORT_TERM_MODEL = 3;
private static final int MSG_UPDATE_FOREGROUND_APP = 4;
private static final int MSG_UPDATE_FOREGROUND_APP_SYNC = 5;
+ private static final int MSG_RUN_UPDATE = 6;
// Length of the ambient light horizon used to calculate the long term estimate of ambient
// light.
@@ -360,6 +361,13 @@
return mBrightnessMapper.getDefaultConfig();
}
+ /**
+ * Force recalculate of the state of automatic brightness.
+ */
+ public void update() {
+ mHandler.sendEmptyMessage(MSG_RUN_UPDATE);
+ }
+
private boolean setDisplayPolicy(int policy) {
if (mDisplayPolicy == policy) {
return false;
@@ -910,6 +918,10 @@
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
+ case MSG_RUN_UPDATE:
+ updateAutoBrightness(true /*sendUpdate*/, false /*isManuallySet*/);
+ break;
+
case MSG_UPDATE_AMBIENT_LUX:
updateAmbientLux();
break;
diff --git a/services/core/java/com/android/server/display/BrightnessSetting.java b/services/core/java/com/android/server/display/BrightnessSetting.java
index 8ce7b66..ca7b789 100644
--- a/services/core/java/com/android/server/display/BrightnessSetting.java
+++ b/services/core/java/com/android/server/display/BrightnessSetting.java
@@ -17,19 +17,14 @@
package com.android.server.display;
import android.annotation.NonNull;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.os.PowerManager;
-import android.os.UserHandle;
-import android.provider.Settings;
import android.util.Slog;
-import android.view.Display;
-import java.util.concurrent.CopyOnWriteArrayList;
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.concurrent.CopyOnWriteArraySet;
/**
* Saves brightness to a persistent data store, enabling each logical display to have its own
@@ -39,14 +34,11 @@
private static final String TAG = "BrightnessSetting";
private static final int MSG_BRIGHTNESS_CHANGED = 1;
- private static final Uri BRIGHTNESS_FLOAT_URI =
- Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FLOAT);
- private final PersistentDataStore mPersistentDataStore;
- private final boolean mIsDefaultDisplay;
- private final Context mContext;
+ private final PersistentDataStore mPersistentDataStore;
+ private final DisplayManagerService.SyncRoot mSyncRoot;
+
private final LogicalDisplay mLogicalDisplay;
- private final Object mLock = new Object();
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
@@ -58,37 +50,20 @@
}
};
- private final ContentObserver mBrightnessSettingsObserver = new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- if (selfChange) {
- return;
- }
- if (BRIGHTNESS_FLOAT_URI.equals(uri)) {
- float brightness = getScreenBrightnessSettingFloat();
- setBrightness(brightness, true);
- }
- }
- };
+ private final CopyOnWriteArraySet<BrightnessSettingListener> mListeners =
+ new CopyOnWriteArraySet<>();
- private final CopyOnWriteArrayList<BrightnessSettingListener> mListeners =
- new CopyOnWriteArrayList<BrightnessSettingListener>();
-
+ @GuardedBy("mSyncRoot")
private float mBrightness;
BrightnessSetting(@NonNull PersistentDataStore persistentDataStore,
@NonNull LogicalDisplay logicalDisplay,
- @NonNull Context context) {
+ DisplayManagerService.SyncRoot syncRoot) {
mPersistentDataStore = persistentDataStore;
mLogicalDisplay = logicalDisplay;
- mContext = context;
- mIsDefaultDisplay = mLogicalDisplay.getDisplayIdLocked() == Display.DEFAULT_DISPLAY;
mBrightness = mPersistentDataStore.getBrightness(
mLogicalDisplay.getPrimaryDisplayDeviceLocked());
- if (mIsDefaultDisplay) {
- mContext.getContentResolver().registerContentObserver(BRIGHTNESS_FLOAT_URI,
- false, mBrightnessSettingsObserver);
- }
+ mSyncRoot = syncRoot;
}
/**
@@ -97,16 +72,19 @@
* @return brightness for the current display
*/
public float getBrightness() {
- return mBrightness;
+ synchronized (mSyncRoot) {
+ return mBrightness;
+ }
}
/**
* Registers listener for brightness setting change events.
*/
public void registerListener(BrightnessSettingListener l) {
- if (!mListeners.contains(l)) {
- mListeners.add(l);
+ if (mListeners.contains(l)) {
+ Slog.wtf(TAG, "Duplicate Listener added");
}
+ mListeners.add(l);
}
/**
@@ -119,27 +97,16 @@
}
void setBrightness(float brightness) {
- setBrightness(brightness, false);
- }
-
- private void setBrightness(float brightness, boolean isFromSystemSetting) {
- if (brightness == mBrightness) {
- return;
- }
if (Float.isNaN(brightness)) {
Slog.w(TAG, "Attempting to set invalid brightness");
return;
}
- synchronized (mLock) {
+ synchronized (mSyncRoot) {
+ if (brightness == mBrightness) {
+ return;
+ }
mBrightness = brightness;
-
- // If it didn't come from us
- if (mIsDefaultDisplay && !isFromSystemSetting) {
- Settings.System.putFloatForUser(mContext.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS_FLOAT, brightness,
- UserHandle.USER_CURRENT);
- }
mPersistentDataStore.setBrightness(mLogicalDisplay.getPrimaryDisplayDeviceLocked(),
brightness);
int toSend = Float.floatToIntBits(mBrightness);
@@ -148,12 +115,6 @@
}
}
- private float getScreenBrightnessSettingFloat() {
- return Settings.System.getFloatForUser(mContext.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS_FLOAT, PowerManager.BRIGHTNESS_INVALID_FLOAT,
- UserHandle.USER_CURRENT);
- }
-
private void notifyListeners(float brightness) {
for (BrightnessSettingListener l : mListeners) {
l.onBrightnessChanged(brightness);
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 88f88a8..4c9d0f2 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -39,6 +39,7 @@
import com.android.server.display.config.Point;
import com.android.server.display.config.RefreshRateRange;
import com.android.server.display.config.SensorDetails;
+import com.android.server.display.config.ThermalStatus;
import com.android.server.display.config.XmlParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -657,6 +658,8 @@
mHbmData.timeWindowMillis = hbmTiming.getTimeWindowSecs_all().longValue() * 1000;
mHbmData.timeMaxMillis = hbmTiming.getTimeMaxSecs_all().longValue() * 1000;
mHbmData.timeMinMillis = hbmTiming.getTimeMinSecs_all().longValue() * 1000;
+ mHbmData.thermalStatusLimit = convertThermalStatus(hbm.getThermalStatusLimit_all());
+ mHbmData.allowInLowPowerMode = hbm.getAllowInLowPowerMode_all();
final RefreshRateRange rr = hbm.getRefreshRate_all();
if (rr != null) {
final float min = rr.getMinimum().floatValue();
@@ -743,6 +746,31 @@
}
}
+ private @PowerManager.ThermalStatus int convertThermalStatus(ThermalStatus value) {
+ if (value == null) {
+ return PowerManager.THERMAL_STATUS_NONE;
+ }
+ switch (value) {
+ case none:
+ return PowerManager.THERMAL_STATUS_NONE;
+ case light:
+ return PowerManager.THERMAL_STATUS_LIGHT;
+ case moderate:
+ return PowerManager.THERMAL_STATUS_MODERATE;
+ case severe:
+ return PowerManager.THERMAL_STATUS_SEVERE;
+ case critical:
+ return PowerManager.THERMAL_STATUS_CRITICAL;
+ case emergency:
+ return PowerManager.THERMAL_STATUS_EMERGENCY;
+ case shutdown:
+ return PowerManager.THERMAL_STATUS_SHUTDOWN;
+ default:
+ Slog.wtf(TAG, "Unexpected Thermal Status: " + value);
+ return PowerManager.THERMAL_STATUS_NONE;
+ }
+ }
+
static class SensorData {
public String type;
public String name;
@@ -781,6 +809,12 @@
/** Brightness level at which we transition from normal to high-brightness. */
public float transitionPoint;
+ /** Enable HBM only if the thermal status is not higher than this. */
+ public @PowerManager.ThermalStatus int thermalStatusLimit;
+
+ /** Whether HBM is allowed when {@code Settings.Global.LOW_POWER_MODE} is active. */
+ public boolean allowInLowPowerMode;
+
/** Time window for HBM. */
public long timeWindowMillis;
@@ -792,13 +826,16 @@
HighBrightnessModeData() {}
- HighBrightnessModeData(float minimumLux, float transitionPoint,
- long timeWindowMillis, long timeMaxMillis, long timeMinMillis) {
+ HighBrightnessModeData(float minimumLux, float transitionPoint, long timeWindowMillis,
+ long timeMaxMillis, long timeMinMillis,
+ @PowerManager.ThermalStatus int thermalStatusLimit, boolean allowInLowPowerMode) {
this.minimumLux = minimumLux;
this.transitionPoint = transitionPoint;
this.timeWindowMillis = timeWindowMillis;
this.timeMaxMillis = timeMaxMillis;
this.timeMinMillis = timeMinMillis;
+ this.thermalStatusLimit = thermalStatusLimit;
+ this.allowInLowPowerMode = allowInLowPowerMode;
}
/**
@@ -807,10 +844,12 @@
*/
public void copyTo(@NonNull HighBrightnessModeData other) {
other.minimumLux = minimumLux;
- other.transitionPoint = transitionPoint;
other.timeWindowMillis = timeWindowMillis;
other.timeMaxMillis = timeMaxMillis;
other.timeMinMillis = timeMinMillis;
+ other.transitionPoint = transitionPoint;
+ other.thermalStatusLimit = thermalStatusLimit;
+ other.allowInLowPowerMode = allowInLowPowerMode;
}
@Override
@@ -821,6 +860,8 @@
+ ", timeWindow: " + timeWindowMillis + "ms"
+ ", timeMax: " + timeMaxMillis + "ms"
+ ", timeMin: " + timeMinMillis + "ms"
+ + ", thermalStatusLimit: " + thermalStatusLimit
+ + ", allowInLowPowerMode: " + allowInLowPowerMode
+ "} ";
}
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 79ea108..9d8ca9a 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -399,9 +399,6 @@
// Receives notifications about changes to Settings.
private SettingsObserver mSettingsObserver;
- // Received notifications of the device-state action (such as "fold", "unfold")
- private DeviceStateManager mDeviceStateManager;
-
private final boolean mAllowNonNativeRefreshRateOverride;
private final BrightnessSynchronizer mBrightnessSynchronizer;
@@ -1236,13 +1233,6 @@
adapter.registerLocked();
}
- @VisibleForTesting
- void handleLogicalDisplayAdded(LogicalDisplay display) {
- synchronized (mSyncRoot) {
- handleLogicalDisplayAddedLocked(display);
- }
- }
-
private void handleLogicalDisplayAddedLocked(LogicalDisplay display) {
final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
final int displayId = display.getDisplayIdLocked();
@@ -2107,7 +2097,7 @@
}
final BrightnessSetting brightnessSetting = new BrightnessSetting(mPersistentDataStore,
- display, mContext);
+ display, mSyncRoot);
final DisplayPowerController displayPowerController = new DisplayPowerController(
mContext, mDisplayPowerCallbacks, mPowerHandler, mSensorManager,
mDisplayBlanker, display, mBrightnessTracker, brightnessSetting,
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 555add4..20d364e 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -149,9 +149,6 @@
private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
private static final int REPORTED_TO_POLICY_SCREEN_TURNING_OFF = 3;
- private static final Uri BRIGHTNESS_FLOAT_URI =
- Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FLOAT);
-
private final Object mLock = new Object();
private final Context mContext;
@@ -393,7 +390,7 @@
// The last brightness that was set by the user and not temporary. Set to
// PowerManager.BRIGHTNESS_INVALID_FLOAT when a brightness has yet to be recorded.
- private float mLastUserSetScreenBrightness;
+ private float mLastUserSetScreenBrightness = Float.NaN;
// The screen brightness setting has changed but not taken effect yet. If this is different
// from the current screen brightness setting then this is coming from something other than us
@@ -424,6 +421,14 @@
// PowerManager.BRIGHTNESS_INVALID_FLOAT when there's no temporary adjustment set.
private float mTemporaryAutoBrightnessAdjustment;
+ // Whether a reduce bright colors (rbc) change has been initiated by the user. We want to
+ // retain the current backlight level when rbc is toggled, since rbc additionally makes the
+ // screen appear dimmer using screen colors rather than backlight levels, and therefore we
+ // don't actually want to compensate for this by then in/decreasing the backlight when
+ // toggling this feature.
+ // This should be false during system start up.
+ private boolean mPendingUserRbcChange;
+
// Animators.
private ObjectAnimator mColorFadeOnAnimator;
private ObjectAnimator mColorFadeOffAnimator;
@@ -555,24 +560,25 @@
mCdsi = LocalServices.getService(ColorDisplayServiceInternal.class);
boolean active = mCdsi.setReduceBrightColorsListener(new ReduceBrightColorsListener() {
@Override
- public void onReduceBrightColorsActivationChanged(boolean activated) {
- applyReduceBrightColorsSplineAdjustment();
+ public void onReduceBrightColorsActivationChanged(boolean activated,
+ boolean userInitiated) {
+ applyReduceBrightColorsSplineAdjustment(userInitiated);
}
@Override
public void onReduceBrightColorsStrengthChanged(int strength) {
- applyReduceBrightColorsSplineAdjustment();
+ applyReduceBrightColorsSplineAdjustment(/*userInitiated*/ false);
}
});
if (active) {
- applyReduceBrightColorsSplineAdjustment();
+ applyReduceBrightColorsSplineAdjustment(/*userInitiated*/ false);
}
} else {
mCdsi = null;
}
}
- private void applyReduceBrightColorsSplineAdjustment() {
+ private void applyReduceBrightColorsSplineAdjustment(boolean userInitiated) {
if (mBrightnessMapper == null) {
Log.w(TAG, "No brightness mapping available to recalculate splines");
return;
@@ -583,6 +589,8 @@
adjustedNits[i] = mCdsi.getReduceBrightColorsAdjustedBrightnessNits(mNitsRange[i]);
}
mBrightnessMapper.recalculateSplines(mCdsi.isReduceBrightColorsActivated(), adjustedNits);
+ mPendingUserRbcChange = userInitiated;
+ sendUpdatePowerState();
}
/**
@@ -914,7 +922,7 @@
private void reloadReduceBrightColours() {
if (mCdsi != null && mCdsi.isReduceBrightColorsActivated()) {
- applyReduceBrightColorsSplineAdjustment();
+ applyReduceBrightColorsSplineAdjustment(/*userInitiated*/ false);
}
}
@@ -1518,7 +1526,9 @@
() -> {
sendUpdatePowerStateLocked();
mHandler.post(mOnBrightnessChangeRunnable);
- });
+ // TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern.
+ mAutomaticBrightnessController.update();
+ }, mContext);
}
private void blockScreenOn() {
@@ -2040,15 +2050,21 @@
}
private boolean updateUserSetScreenBrightness() {
+ final boolean brightnessSplineChanged = mPendingUserRbcChange;
+ if (mPendingUserRbcChange && !Float.isNaN(mCurrentScreenBrightnessSetting)) {
+ mLastUserSetScreenBrightness = mCurrentScreenBrightnessSetting;
+ }
+ mPendingUserRbcChange = false;
+
if ((Float.isNaN(mPendingScreenBrightnessSetting)
|| mPendingScreenBrightnessSetting < 0.0f)) {
- return false;
+ return brightnessSplineChanged;
}
if (BrightnessSynchronizer.floatEquals(
mCurrentScreenBrightnessSetting, mPendingScreenBrightnessSetting)) {
mPendingScreenBrightnessSetting = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
- return false;
+ return brightnessSplineChanged;
}
setCurrentScreenBrightness(mPendingScreenBrightnessSetting);
mLastUserSetScreenBrightness = mPendingScreenBrightnessSetting;
diff --git a/services/core/java/com/android/server/display/HighBrightnessModeController.java b/services/core/java/com/android/server/display/HighBrightnessModeController.java
index 57a8c4b..d629422 100644
--- a/services/core/java/com/android/server/display/HighBrightnessModeController.java
+++ b/services/core/java/com/android/server/display/HighBrightnessModeController.java
@@ -16,11 +16,21 @@
package com.android.server.display;
+import android.content.Context;
+import android.database.ContentObserver;
import android.hardware.display.BrightnessInfo;
+import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IThermalEventListener;
+import android.os.IThermalService;
import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
+import android.os.Temperature;
+import android.os.UserHandle;
+import android.provider.Settings;
import android.util.Slog;
import android.util.TimeUtils;
import android.view.SurfaceControlHdrLayerInfoListener;
@@ -52,6 +62,10 @@
private final Runnable mHbmChangeCallback;
private final Runnable mRecalcRunnable;
private final Clock mClock;
+ private final SkinThermalStatusObserver mSkinThermalStatusObserver;
+ private final Context mContext;
+ private final SettingsObserver mSettingsObserver;
+ private final Injector mInjector;
private SurfaceControlHdrLayerInfoListener mHdrListener;
private HighBrightnessModeData mHbmData;
@@ -63,6 +77,8 @@
private float mAutoBrightness;
private int mHbmMode = BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
private boolean mIsHdrLayerPresent = false;
+ private boolean mIsThermalStatusWithinLimit = true;
+ private boolean mIsBlockedByLowPowerMode = false;
/**
* If HBM is currently running, this is the start time for the current HBM session.
@@ -72,29 +88,33 @@
/**
* List of previous HBM-events ordered from most recent to least recent.
* Meant to store only the events that fall into the most recent
- * {@link mHbmData.timeWindowSecs}.
+ * {@link mHbmData.timeWindowMillis}.
*/
private LinkedList<HbmEvent> mEvents = new LinkedList<>();
HighBrightnessModeController(Handler handler, IBinder displayToken, float brightnessMin,
- float brightnessMax, HighBrightnessModeData hbmData, Runnable hbmChangeCallback) {
- this(SystemClock::uptimeMillis, handler, displayToken, brightnessMin, brightnessMax,
- hbmData, hbmChangeCallback);
+ float brightnessMax, HighBrightnessModeData hbmData, Runnable hbmChangeCallback,
+ Context context) {
+ this(new Injector(), handler, displayToken, brightnessMin, brightnessMax,
+ hbmData, hbmChangeCallback, context);
}
@VisibleForTesting
- HighBrightnessModeController(Clock clock, Handler handler, IBinder displayToken,
+ HighBrightnessModeController(Injector injector, Handler handler, IBinder displayToken,
float brightnessMin, float brightnessMax, HighBrightnessModeData hbmData,
- Runnable hbmChangeCallback) {
- mClock = clock;
+ Runnable hbmChangeCallback, Context context) {
+ mInjector = injector;
+ mClock = injector.getClock();
mHandler = handler;
mBrightnessMin = brightnessMin;
mBrightnessMax = brightnessMax;
mHbmChangeCallback = hbmChangeCallback;
+ mContext = context;
mAutoBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mRecalcRunnable = this::recalculateTimeAllowance;
mHdrListener = new HdrListener();
-
+ mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler);
+ mSettingsObserver = new SettingsObserver(mHandler);
resetHbmData(displayToken, hbmData);
}
@@ -178,14 +198,26 @@
void stop() {
registerHdrListener(null /*displayToken*/);
+ mSkinThermalStatusObserver.stopObserving();
+ mSettingsObserver.stopObserving();
}
void resetHbmData(IBinder displayToken, HighBrightnessModeData hbmData) {
mHbmData = hbmData;
unregisterHdrListener();
+ mSkinThermalStatusObserver.stopObserving();
+ mSettingsObserver.stopObserving();
if (deviceSupportsHbm()) {
registerHdrListener(displayToken);
recalculateTimeAllowance();
+ if (mHbmData.thermalStatusLimit > PowerManager.THERMAL_STATUS_NONE) {
+ mIsThermalStatusWithinLimit = true;
+ mSkinThermalStatusObserver.startObserving();
+ }
+ if (!mHbmData.allowInLowPowerMode) {
+ mIsBlockedByLowPowerMode = false;
+ mSettingsObserver.startObserving();
+ }
}
}
@@ -208,6 +240,8 @@
pw.println(" mBrightnessMin=" + mBrightnessMin);
pw.println(" mBrightnessMax=" + mBrightnessMax);
pw.println(" mRunningStartTimeMillis=" + TimeUtils.formatUptime(mRunningStartTimeMillis));
+ pw.println(" mIsThermalStatusWithinLimit=" + mIsThermalStatusWithinLimit);
+ pw.println(" mIsBlockedByLowPowerMode=" + mIsBlockedByLowPowerMode);
pw.println(" mEvents=");
final long currentTime = mClock.uptimeMillis();
long lastStartTime = currentTime;
@@ -221,6 +255,8 @@
}
lastStartTime = dumpHbmEvent(pw, event);
}
+
+ mSkinThermalStatusObserver.dump(pw);
}
private long dumpHbmEvent(PrintWriter pw, HbmEvent event) {
@@ -234,7 +270,8 @@
private boolean isCurrentlyAllowed() {
return mIsHdrLayerPresent
- || (mIsAutoBrightnessEnabled && mIsTimeAvailable && mIsInAllowedAmbientRange);
+ || (mIsAutoBrightnessEnabled && mIsTimeAvailable && mIsInAllowedAmbientRange
+ && mIsThermalStatusWithinLimit && !mIsBlockedByLowPowerMode);
}
private boolean deviceSupportsHbm() {
@@ -327,6 +364,12 @@
+ ", remainingAllowedTime: " + remainingTime
+ ", isLuxHigh: " + mIsInAllowedAmbientRange
+ ", isHBMCurrentlyAllowed: " + isCurrentlyAllowed()
+ + ", isHdrLayerPresent: " + mIsHdrLayerPresent
+ + ", isAutoBrightnessEnabled: " + mIsAutoBrightnessEnabled
+ + ", mIsTimeAvailable: " + mIsTimeAvailable
+ + ", mIsInAllowedAmbientRange: " + mIsInAllowedAmbientRange
+ + ", mIsThermalStatusWithinLimit: " + mIsThermalStatusWithinLimit
+ + ", mIsBlockedByLowPowerMode: " + mIsBlockedByLowPowerMode
+ ", brightness: " + mAutoBrightness
+ ", RunningStartTimeMillis: " + mRunningStartTimeMillis
+ ", nextTimeout: " + (nextTimeout != -1 ? (nextTimeout - currentTime) : -1)
@@ -337,8 +380,11 @@
mHandler.removeCallbacks(mRecalcRunnable);
mHandler.postAtTime(mRecalcRunnable, nextTimeout + 1);
}
-
// Update the state of the world
+ updateHbmMode();
+ }
+
+ private void updateHbmMode() {
int newHbmMode = calculateHighBrightnessMode();
if (mHbmMode != newHbmMode) {
mHbmMode = newHbmMode;
@@ -409,4 +455,141 @@
});
}
}
+
+ private final class SkinThermalStatusObserver extends IThermalEventListener.Stub {
+ private final Injector mInjector;
+ private final Handler mHandler;
+
+ private IThermalService mThermalService;
+ private boolean mStarted;
+
+ SkinThermalStatusObserver(Injector injector, Handler handler) {
+ mInjector = injector;
+ mHandler = handler;
+ }
+
+ @Override
+ public void notifyThrottling(Temperature temp) {
+ if (DEBUG) {
+ Slog.d(TAG, "New thermal throttling status "
+ + ", current thermal status = " + temp.getStatus()
+ + ", threshold = " + mHbmData.thermalStatusLimit);
+ }
+ mHandler.post(() -> {
+ mIsThermalStatusWithinLimit = temp.getStatus() <= mHbmData.thermalStatusLimit;
+ // This recalculates HbmMode and runs mHbmChangeCallback if the mode has changed
+ updateHbmMode();
+ });
+ }
+
+ void startObserving() {
+ if (mStarted) {
+ if (DEBUG) {
+ Slog.d(TAG, "Thermal status observer already started");
+ }
+ return;
+ }
+ mThermalService = mInjector.getThermalService();
+ if (mThermalService == null) {
+ Slog.w(TAG, "Could not observe thermal status. Service not available");
+ return;
+ }
+ try {
+ // We get a callback immediately upon registering so there's no need to query
+ // for the current value.
+ mThermalService.registerThermalEventListenerWithType(this, Temperature.TYPE_SKIN);
+ mStarted = true;
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to register thermal status listener", e);
+ }
+ }
+
+ void stopObserving() {
+ mIsThermalStatusWithinLimit = true;
+ if (!mStarted) {
+ if (DEBUG) {
+ Slog.d(TAG, "Stop skipped because thermal status observer not started");
+ }
+ return;
+ }
+ try {
+ mThermalService.unregisterThermalEventListener(this);
+ mStarted = false;
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to unregister thermal status listener", e);
+ }
+ mThermalService = null;
+ }
+
+ void dump(PrintWriter writer) {
+ writer.println(" SkinThermalStatusObserver:");
+ writer.println(" mStarted: " + mStarted);
+ if (mThermalService != null) {
+ writer.println(" ThermalService available");
+ } else {
+ writer.println(" ThermalService not available");
+ }
+ }
+ }
+
+ private final class SettingsObserver extends ContentObserver {
+ private final Uri mLowPowerModeSetting = Settings.Global.getUriFor(
+ Settings.Global.LOW_POWER_MODE);
+ private boolean mStarted;
+
+ SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ updateLowPower();
+ }
+
+ void startObserving() {
+ if (!mStarted) {
+ mContext.getContentResolver().registerContentObserver(mLowPowerModeSetting,
+ false /*notifyForDescendants*/, this, UserHandle.USER_ALL);
+ mStarted = true;
+ updateLowPower();
+ }
+ }
+
+ void stopObserving() {
+ mIsBlockedByLowPowerMode = false;
+ if (mStarted) {
+ mContext.getContentResolver().unregisterContentObserver(this);
+ mStarted = false;
+ }
+ }
+
+ private void updateLowPower() {
+ final boolean isLowPowerMode = isLowPowerMode();
+ if (isLowPowerMode == mIsBlockedByLowPowerMode) {
+ return;
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "Settings.Global.LOW_POWER_MODE enabled: " + isLowPowerMode);
+ }
+ mIsBlockedByLowPowerMode = isLowPowerMode;
+ // this recalculates HbmMode and runs mHbmChangeCallback if the mode has changed
+ updateHbmMode();
+ }
+
+ private boolean isLowPowerMode() {
+ return Settings.Global.getInt(
+ mContext.getContentResolver(), Settings.Global.LOW_POWER_MODE, 0) != 0;
+ }
+ }
+
+ public static class Injector {
+ public Clock getClock() {
+ return SystemClock::uptimeMillis;
+ }
+
+ public IThermalService getThermalService() {
+ return IThermalService.Stub.asInterface(
+ ServiceManager.getService(Context.THERMAL_SERVICE));
+ }
+ }
}
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index 7fa0b21..bccd4c4 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -355,7 +355,7 @@
updateDisplayWhiteBalanceStatus();
break;
case Secure.REDUCE_BRIGHT_COLORS_ACTIVATED:
- onReduceBrightColorsActivationChanged();
+ onReduceBrightColorsActivationChanged(/*userInitiated*/ true);
mHandler.sendEmptyMessage(MSG_APPLY_REDUCE_BRIGHT_COLORS);
break;
case Secure.REDUCE_BRIGHT_COLORS_LEVEL:
@@ -437,7 +437,7 @@
onReduceBrightColorsStrengthLevelChanged();
final boolean reset = resetReduceBrightColors();
if (!reset) {
- onReduceBrightColorsActivationChanged();
+ onReduceBrightColorsActivationChanged(/*userInitiated*/ false);
mHandler.sendEmptyMessage(MSG_APPLY_REDUCE_BRIGHT_COLORS);
}
}
@@ -614,7 +614,7 @@
isAccessiblityInversionEnabled() ? MATRIX_INVERT_COLOR : null);
}
- private void onReduceBrightColorsActivationChanged() {
+ private void onReduceBrightColorsActivationChanged(boolean userInitiated) {
if (mCurrentUser == UserHandle.USER_NULL) {
return;
}
@@ -622,7 +622,8 @@
Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 0, mCurrentUser) == 1;
mReduceBrightColorsTintController.setActivated(activated);
if (mReduceBrightColorsListener != null) {
- mReduceBrightColorsListener.onReduceBrightColorsActivationChanged(activated);
+ mReduceBrightColorsListener.onReduceBrightColorsActivationChanged(activated,
+ userInitiated);
}
}
@@ -1551,7 +1552,7 @@
/**
* Notify that the reduce bright colors activation status has changed.
*/
- void onReduceBrightColorsActivationChanged(boolean activated);
+ void onReduceBrightColorsActivationChanged(boolean activated, boolean userInitiated);
/**
* Notify that the reduce bright colors strength has changed.
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index a3daae4..bccc52f 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -570,10 +570,12 @@
protected final void migrateToXml() {
for (UserInfo user : mUm.getUsers()) {
final ContentResolver cr = mContext.getContentResolver();
- addApprovedList(Settings.Secure.getStringForUser(
- cr,
- getConfig().secureSettingName,
- user.id), user.id, true);
+ if (!TextUtils.isEmpty(getConfig().secureSettingName)) {
+ addApprovedList(Settings.Secure.getStringForUser(
+ cr,
+ getConfig().secureSettingName,
+ user.id), user.id, true);
+ }
if (!TextUtils.isEmpty(getConfig().secondarySettingName)) {
addApprovedList(Settings.Secure.getStringForUser(
cr,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index faa37a03..0a7053c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -6179,6 +6179,9 @@
}
if (succeeded) {
+ // Clear the uid cache after we installed a new package.
+ mPerUidReadTimeoutsCache = null;
+
// Send the removed broadcasts
if (res.removedInfo != null) {
res.removedInfo.sendPackageRemovedBroadcasts(killApp, false /*removedBySystem*/);
@@ -11608,9 +11611,17 @@
return resolveContentProviderInternal(name, flags, userId);
}
+ public ProviderInfo resolveContentProvider(String name, int flags, int userId, int callingUid) {
+ return resolveContentProviderInternal(name, flags, userId, callingUid);
+ }
+
private ProviderInfo resolveContentProviderInternal(String name, int flags, int userId) {
+ return resolveContentProviderInternal(name, flags, userId, Binder.getCallingUid());
+ }
+
+ private ProviderInfo resolveContentProviderInternal(String name, int flags, int userId,
+ int callingUid) {
if (!mUserManager.exists(userId)) return null;
- final int callingUid = Binder.getCallingUid();
flags = updateFlagsForComponent(flags, userId);
final ProviderInfo providerInfo = mComponentResolver.queryProvider(name, flags, userId);
boolean checkedGrants = false;
@@ -27778,6 +27789,13 @@
}
@Override
+ public ProviderInfo resolveContentProvider(String name, int flags, int userId,
+ int callingUid) {
+ return PackageManagerService.this.resolveContentProviderInternal(
+ name, flags, userId, callingUid);
+ }
+
+ @Override
public void addIsolatedUid(int isolatedUid, int ownerUid) {
synchronized (mLock) {
mIsolatedOwners.put(isolatedUid, ownerUid);
diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java
index fc7628c..6014d0c 100644
--- a/services/core/java/com/android/server/power/hint/HintManagerService.java
+++ b/services/core/java/com/android/server/power/hint/HintManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.power.hint;
import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
import android.app.IUidObserver;
import android.content.Context;
import android.os.Binder;
@@ -33,12 +34,16 @@
import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.server.FgThread;
+import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.utils.Slogf;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
/** An hint service implementation that runs in System Server process. */
public final class HintManagerService extends SystemService {
@@ -56,6 +61,8 @@
private final NativeWrapper mNativeWrapper;
+ private final ActivityManagerInternal mAmInternal;
+
@VisibleForTesting final IHintManager.Stub mService = new BinderService();
public HintManagerService(Context context) {
@@ -70,6 +77,8 @@
mNativeWrapper.halInit();
mHintSessionPreferredRate = mNativeWrapper.halGetHintSessionPreferredRate();
mUidObserver = new UidObserver();
+ mAmInternal = Objects.requireNonNull(
+ LocalServices.getService(ActivityManagerInternal.class));
}
@VisibleForTesting
@@ -85,7 +94,7 @@
@Override
public void onStart() {
- publishBinderService(Context.PERFORMANCE_HINT_SERVICE, mService, /* allowIsolated= */ true);
+ publishBinderService(Context.PERFORMANCE_HINT_SERVICE, mService);
}
@Override
@@ -243,12 +252,30 @@
return mService;
}
- private boolean checkTidValid(int tgid, int [] tids) {
- // Make sure all tids belongs to the same process.
+ private boolean checkTidValid(int uid, int tgid, int [] tids) {
+ // Make sure all tids belongs to the same UID (including isolated UID),
+ // tids can belong to different application processes.
+ List<Integer> eligiblePids = mAmInternal.getIsolatedProcesses(uid);
+ if (eligiblePids == null) {
+ eligiblePids = new ArrayList<>();
+ }
+ eligiblePids.add(tgid);
+
for (int threadId : tids) {
- if (!Process.isThreadInProcess(tgid, threadId)) {
- return false;
+ final String[] procStatusKeys = new String[] {
+ "Uid:",
+ "Tgid:"
+ };
+ long[] output = new long[procStatusKeys.length];
+ Process.readProcLines("/proc/" + threadId + "/status", procStatusKeys, output);
+ int uidOfThreadId = (int) output[0];
+ int pidOfThreadId = (int) output[1];
+
+ // use PID check for isolated processes, use UID check for non-isolated processes.
+ if (eligiblePids.contains(pidOfThreadId) || uidOfThreadId == uid) {
+ continue;
}
+ return false;
}
return true;
}
@@ -264,27 +291,25 @@
Preconditions.checkArgument(tids.length != 0, "tids should"
+ " not be empty.");
- int uid = Binder.getCallingUid();
- int tid = Binder.getCallingPid();
- int pid = Process.getThreadGroupLeader(tid);
-
+ final int callingUid = Binder.getCallingUid();
+ final int callingTgid = Process.getThreadGroupLeader(Binder.getCallingPid());
final long identity = Binder.clearCallingIdentity();
try {
- if (!checkTidValid(pid, tids)) {
- throw new SecurityException("Some tid doesn't belong to the process");
+ if (!checkTidValid(callingUid, callingTgid, tids)) {
+ throw new SecurityException("Some tid doesn't belong to the application");
}
- long halSessionPtr = mNativeWrapper.halCreateHintSession(pid, uid, tids,
- durationNanos);
+ long halSessionPtr = mNativeWrapper.halCreateHintSession(callingTgid, callingUid,
+ tids, durationNanos);
if (halSessionPtr == 0) return null;
- AppHintSession hs = new AppHintSession(uid, pid, tids, token,
+ AppHintSession hs = new AppHintSession(callingUid, callingTgid, tids, token,
halSessionPtr, durationNanos);
synchronized (mLock) {
- ArrayMap<IBinder, AppHintSession> tokenMap = mActiveSessions.get(uid);
+ ArrayMap<IBinder, AppHintSession> tokenMap = mActiveSessions.get(callingUid);
if (tokenMap == null) {
tokenMap = new ArrayMap<>(1);
- mActiveSessions.put(uid, tokenMap);
+ mActiveSessions.put(callingUid, tokenMap);
}
tokenMap.put(token, hs);
return hs;
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 6255d77..3a7e13b 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -671,20 +671,8 @@
@Override
public void collapsePanels() {
- int uid = Binder.getCallingUid();
- int pid = Binder.getCallingPid();
- if (CompatChanges.isChangeEnabled(LOCK_DOWN_COLLAPSE_STATUS_BAR, uid)) {
- enforceStatusBar();
- } else {
- if (mContext.checkPermission(Manifest.permission.STATUS_BAR, pid, uid)
- != PackageManager.PERMISSION_GRANTED) {
- enforceExpandStatusBar();
- if (!mActivityTaskManager.canCloseSystemDialogs(pid, uid)) {
- Slog.e(TAG, "Permission Denial: Method collapsePanels() requires permission "
- + Manifest.permission.STATUS_BAR + ", ignoring call.");
- return;
- }
- }
+ if (!checkCanCollapseStatusBar("collapsePanels")) {
+ return;
}
if (mBar != null) {
@@ -697,7 +685,9 @@
@Override
public void togglePanel() {
- enforceExpandStatusBar();
+ if (!checkCanCollapseStatusBar("togglePanel")) {
+ return;
+ }
if (isDisable2FlagSet(DISABLE2_NOTIFICATION_SHADE)) {
return;
@@ -758,7 +748,9 @@
@Override
public void handleSystemKey(int key) throws RemoteException {
- enforceExpandStatusBar();
+ if (!checkCanCollapseStatusBar("handleSystemKey")) {
+ return;
+ }
if (mBar != null) {
try {
@@ -1201,6 +1193,29 @@
"StatusBarManagerService");
}
+ /**
+ * For targetSdk S+ we require STATUS_BAR. For targetSdk < S, we only require EXPAND_STATUS_BAR
+ * but also require that it falls into one of the allowed use-cases to lock down abuse vector.
+ */
+ private boolean checkCanCollapseStatusBar(String method) {
+ int uid = Binder.getCallingUid();
+ int pid = Binder.getCallingUid();
+ if (CompatChanges.isChangeEnabled(LOCK_DOWN_COLLAPSE_STATUS_BAR, uid)) {
+ enforceStatusBar();
+ } else {
+ if (mContext.checkPermission(Manifest.permission.STATUS_BAR, pid, uid)
+ != PackageManager.PERMISSION_GRANTED) {
+ enforceExpandStatusBar();
+ if (!mActivityTaskManager.canCloseSystemDialogs(pid, uid)) {
+ Slog.e(TAG, "Permission Denial: Method " + method + "() requires permission "
+ + Manifest.permission.STATUS_BAR + ", ignoring call.");
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
// ================================================================================
// Callbacks from the status bar service.
// ================================================================================
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index 44545ed..4e453f3 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -1061,6 +1061,12 @@
PackageManager.GET_URI_PERMISSION_PATTERNS | pmFlags, userHandle);
}
+ private ProviderInfo getProviderInfo(String authority, int userHandle, int pmFlags,
+ int callingUid) {
+ return mPmInternal.resolveContentProvider(authority,
+ PackageManager.GET_URI_PERMISSION_PATTERNS | pmFlags, userHandle, callingUid);
+ }
+
/**
* Check if the targetPkg can be granted permission to access uri by
* the callingUid using the given modeFlags. Throws a security exception
@@ -1106,7 +1112,7 @@
final String authority = grantUri.uri.getAuthority();
final ProviderInfo pi = getProviderInfo(authority, grantUri.sourceUserId,
- MATCH_DEBUG_TRIAGED_MISSING);
+ MATCH_DEBUG_TRIAGED_MISSING, callingUid);
if (pi == null) {
Slog.w(TAG, "No content provider found for permission check: " +
grantUri.uri.toSafeString());
diff --git a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
index 0b8ed18..7ddd135 100644
--- a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
+++ b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
@@ -460,6 +460,10 @@
private final Map<Network, UnderlyingNetworkRecord.Builder>
mUnderlyingNetworkRecordBuilders = new ArrayMap<>();
+ UnderlyingNetworkListener() {
+ super(NetworkCallback.FLAG_INCLUDE_LOCATION_INFO);
+ }
+
private TreeSet<UnderlyingNetworkRecord> getSortedUnderlyingNetworks() {
TreeSet<UnderlyingNetworkRecord> sorted =
new TreeSet<>(
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index c0a1d92..4f48442 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -99,16 +99,24 @@
private boolean mLowPowerMode;
VibrationSettings(Context context, Handler handler) {
+ this(context, handler,
+ context.getResources().getInteger(
+ com.android.internal.R.integer.config_vibrationWaveformRampDownDuration),
+ context.getResources().getInteger(
+ com.android.internal.R.integer.config_vibrationWaveformRampStepDuration));
+ }
+
+ @VisibleForTesting
+ VibrationSettings(Context context, Handler handler, int rampDownDuration,
+ int rampStepDuration) {
mContext = context;
mSettingObserver = new SettingsObserver(handler);
mUidObserver = new UidObserver();
mUserReceiver = new UserObserver();
// TODO(b/191150049): move these to vibrator static config file
- mRampStepDuration = context.getResources().getInteger(
- com.android.internal.R.integer.config_vibrationWaveformRampStepDuration);
- mRampDownDuration = context.getResources().getInteger(
- com.android.internal.R.integer.config_vibrationWaveformRampDownDuration);
+ mRampDownDuration = rampDownDuration;
+ mRampStepDuration = rampStepDuration;
VibrationEffect clickEffect = createEffectFromResource(
com.android.internal.R.array.config_virtualKeyVibePattern);
diff --git a/services/core/java/com/android/server/vibrator/VibrationThread.java b/services/core/java/com/android/server/vibrator/VibrationThread.java
index 45d5111..0386372 100644
--- a/services/core/java/com/android/server/vibrator/VibrationThread.java
+++ b/services/core/java/com/android/server/vibrator/VibrationThread.java
@@ -61,6 +61,9 @@
*/
private static final long CALLBACKS_EXTRA_TIMEOUT = 100;
+ /** Threshold to prevent the ramp off steps from trying to set extremely low amplitudes. */
+ private static final float RAMP_OFF_AMPLITUDE_MIN = 1e-3f;
+
/** Fixed large duration used to note repeating vibrations to {@link IBatteryStats}. */
private static final long BATTERY_STATS_REPEATING_VIBRATION_DURATION = 5_000;
@@ -87,26 +90,33 @@
/** Callback triggered to cancel a prepared synced vibration. */
void cancelSyncedVibration();
- /** Callback triggered when vibration thread is complete. */
- void onVibrationEnded(long vibrationId, Vibration.Status status);
+ /** Callback triggered when the vibration is complete. */
+ void onVibrationCompleted(long vibrationId, Vibration.Status status);
+
+ /** Callback triggered when the vibrators are released after the thread is complete. */
+ void onVibratorsReleased();
}
private final Object mLock = new Object();
private final WorkSource mWorkSource = new WorkSource();
private final PowerManager.WakeLock mWakeLock;
private final IBatteryStats mBatteryStatsService;
+ private final VibrationSettings mVibrationSettings;
private final DeviceVibrationEffectAdapter mDeviceEffectAdapter;
private final Vibration mVibration;
private final VibrationCallbacks mCallbacks;
private final SparseArray<VibratorController> mVibrators = new SparseArray<>();
private final StepQueue mStepQueue = new StepQueue();
+ private volatile boolean mStop;
private volatile boolean mForceStop;
- VibrationThread(Vibration vib, DeviceVibrationEffectAdapter effectAdapter,
+ VibrationThread(Vibration vib, VibrationSettings vibrationSettings,
+ DeviceVibrationEffectAdapter effectAdapter,
SparseArray<VibratorController> availableVibrators, PowerManager.WakeLock wakeLock,
IBatteryStats batteryStatsService, VibrationCallbacks callbacks) {
mVibration = vib;
+ mVibrationSettings = vibrationSettings;
mDeviceEffectAdapter = effectAdapter;
mCallbacks = callbacks;
mWakeLock = wakeLock;
@@ -145,8 +155,8 @@
mWakeLock.acquire();
try {
mVibration.token.linkToDeath(this, 0);
- Vibration.Status status = playVibration();
- mCallbacks.onVibrationEnded(mVibration.id, status);
+ playVibration();
+ mCallbacks.onVibratorsReleased();
} catch (RemoteException e) {
Slog.e(TAG, "Error linking vibration to token death", e);
} finally {
@@ -155,9 +165,13 @@
}
}
- /** Cancel current vibration and shuts down the thread gracefully. */
+ /** Cancel current vibration and ramp down the vibrators gracefully. */
public void cancel() {
- mForceStop = true;
+ if (mStop) {
+ // Already cancelled, running clean-up steps.
+ return;
+ }
+ mStop = true;
synchronized (mLock) {
if (DEBUG) {
Slog.d(TAG, "Vibration cancelled");
@@ -166,6 +180,21 @@
}
}
+ /** Cancel current vibration and shuts off the vibrators immediately. */
+ public void cancelImmediately() {
+ if (mForceStop) {
+ // Already forced the thread to stop, wait for it to finish.
+ return;
+ }
+ mStop = mForceStop = true;
+ synchronized (mLock) {
+ if (DEBUG) {
+ Slog.d(TAG, "Vibration cancelled immediately");
+ }
+ mLock.notify();
+ }
+ }
+
/** Notify current vibration that a synced step has completed. */
public void syncedVibrationComplete() {
synchronized (mLock) {
@@ -190,17 +219,18 @@
}
}
- private Vibration.Status playVibration() {
+ private void playVibration() {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "playVibration");
try {
- CombinedVibration.Sequential effect = toSequential(mVibration.getEffect());
- mStepQueue.offer(new StartVibrateStep(effect));
+ CombinedVibration.Sequential sequentialEffect = toSequential(mVibration.getEffect());
+ final int sequentialEffectSize = sequentialEffect.getEffects().size();
+ mStepQueue.offer(new StartVibrateStep(sequentialEffect));
- int stepsPlayed = 0;
+ Vibration.Status status = null;
while (!mStepQueue.isEmpty()) {
long waitTime = mStepQueue.calculateWaitTime();
if (waitTime <= 0) {
- stepsPlayed += mStepQueue.consumeNext();
+ mStepQueue.consumeNext();
} else {
synchronized (mLock) {
try {
@@ -209,17 +239,33 @@
}
}
}
+ Vibration.Status currentStatus = mStop ? Vibration.Status.CANCELLED
+ : mStepQueue.calculateVibrationStatus(sequentialEffectSize);
+ if (status == null && currentStatus != Vibration.Status.RUNNING) {
+ // First time vibration stopped running, start clean-up tasks and notify
+ // callback immediately.
+ status = currentStatus;
+ mCallbacks.onVibrationCompleted(mVibration.id, status);
+ if (status == Vibration.Status.CANCELLED) {
+ mStepQueue.cancel();
+ }
+ }
if (mForceStop) {
- mStepQueue.cancel();
- return Vibration.Status.CANCELLED;
+ // Cancel every step and stop playing them right away, even clean-up steps.
+ mStepQueue.cancelImmediately();
+ break;
}
}
- // Some effects might be ignored because the specified vibrator don't exist or doesn't
- // support the effect. We only report ignored here if nothing was played besides the
- // StartVibrateStep (which means every attempt to turn on the vibrator was ignored).
- return stepsPlayed > effect.getEffects().size()
- ? Vibration.Status.FINISHED : Vibration.Status.IGNORED_UNSUPPORTED;
+ if (status == null) {
+ status = mStepQueue.calculateVibrationStatus(sequentialEffectSize);
+ if (status == Vibration.Status.RUNNING) {
+ Slog.w(TAG, "Something went wrong, step queue completed but vibration status"
+ + " is still RUNNING for vibration " + mVibration.id);
+ status = Vibration.Status.FINISHED;
+ }
+ mCallbacks.onVibrationCompleted(mVibration.id, status);
+ }
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
@@ -260,12 +306,9 @@
segmentIndex = effect.getRepeatIndex();
}
if (segmentIndex < 0) {
- if (vibratorOffTimeout > SystemClock.uptimeMillis()) {
- // No more segments to play, last step is to wait for the vibrator to complete
- return new OffStep(vibratorOffTimeout, controller);
- } else {
- return null;
- }
+ // No more segments to play, last step is to complete the vibration on this vibrator.
+ return new CompleteStep(startTime, /* cancelled= */ false, controller,
+ vibratorOffTimeout);
}
VibrationEffectSegment segment = effect.getSegments().get(segmentIndex);
@@ -299,8 +342,18 @@
@GuardedBy("mLock")
private final Queue<Step> mPendingOnVibratorCompleteSteps = new LinkedList<>();
+ @GuardedBy("mLock")
+ private int mPendingVibrateSteps;
+ @GuardedBy("mLock")
+ private int mConsumedStartVibrateSteps;
+ @GuardedBy("mLock")
+ private int mSuccessfulVibratorOnSteps;
+
public void offer(@NonNull Step step) {
synchronized (mLock) {
+ if (!step.isCleanUp()) {
+ mPendingVibrateSteps++;
+ }
mNextSteps.offer(step);
}
}
@@ -311,6 +364,24 @@
}
}
+ /**
+ * Calculate the {@link Vibration.Status} based on the current queue state and the expected
+ * number of {@link StartVibrateStep} to be played.
+ */
+ public Vibration.Status calculateVibrationStatus(int expectedStartVibrateSteps) {
+ synchronized (mLock) {
+ if (mPendingVibrateSteps > 0
+ || mConsumedStartVibrateSteps < expectedStartVibrateSteps) {
+ return Vibration.Status.RUNNING;
+ }
+ if (mSuccessfulVibratorOnSteps > 0) {
+ return Vibration.Status.FINISHED;
+ }
+ // If no step was able to turn the vibrator ON successfully.
+ return Vibration.Status.IGNORED_UNSUPPORTED;
+ }
+ }
+
/** Returns the time in millis to wait before calling {@link #consumeNext()}. */
public long calculateWaitTime() {
Step nextStep;
@@ -330,18 +401,28 @@
*
* @return the number of steps played
*/
- public int consumeNext() {
+ public void consumeNext() {
Step nextStep = pollNext();
if (nextStep != null) {
// This might turn on the vibrator and have a HAL latency. Execute this outside any
// lock to avoid blocking other interactions with the thread.
List<Step> nextSteps = nextStep.play();
synchronized (mLock) {
+ if (nextStep.getVibratorOnDuration() > 0) {
+ mSuccessfulVibratorOnSteps++;
+ }
+ if (nextStep instanceof StartVibrateStep) {
+ mConsumedStartVibrateSteps++;
+ }
+ if (!nextStep.isCleanUp()) {
+ mPendingVibrateSteps--;
+ }
+ for (int i = 0; i < nextSteps.size(); i++) {
+ mPendingVibrateSteps += nextSteps.get(i).isCleanUp() ? 0 : 1;
+ }
mNextSteps.addAll(nextSteps);
}
- return 1;
}
- return 0;
}
/**
@@ -368,16 +449,38 @@
}
/**
- * Cancel the current queue, clearing all remaining steps.
+ * Cancel the current queue, replacing all remaining steps with respective clean-up steps.
*
- * <p>This will remove and trigger {@link Step#cancel()} in all steps, in order.
+ * <p>This will remove all steps and replace them with respective
+ * {@link Step#cancel()}.
*/
public void cancel() {
+ List<Step> cleanUpSteps = new ArrayList<>();
+ Step step;
+ while ((step = pollNext()) != null) {
+ cleanUpSteps.addAll(step.cancel());
+ }
+ synchronized (mLock) {
+ // All steps generated by Step.cancel() should be clean-up steps.
+ mPendingVibrateSteps = 0;
+ mNextSteps.addAll(cleanUpSteps);
+ }
+ }
+
+ /**
+ * Cancel the current queue immediately, clearing all remaining steps and skipping clean-up.
+ *
+ * <p>This will remove and trigger {@link Step#cancelImmediately()} in all steps, in order.
+ */
+ public void cancelImmediately() {
Step step;
while ((step = pollNext()) != null) {
// This might turn off the vibrator and have a HAL latency. Execute this outside
// any lock to avoid blocking other interactions with the thread.
- step.cancel();
+ step.cancelImmediately();
+ }
+ synchronized (mLock) {
+ mPendingVibrateSteps = 0;
}
}
@@ -406,12 +509,37 @@
this.startTime = startTime;
}
+ /**
+ * Returns true if this step is a clean up step and not part of a {@link VibrationEffect} or
+ * {@link CombinedVibration}.
+ */
+ public boolean isCleanUp() {
+ return false;
+ }
+
/** Play this step, returning a (possibly empty) list of next steps. */
@NonNull
public abstract List<Step> play();
- /** Cancel this pending step. */
- public void cancel() {
+ /**
+ * Cancel this pending step and return a (possibly empty) list of clean-up steps that should
+ * be played to gracefully cancel this step.
+ */
+ @NonNull
+ public abstract List<Step> cancel();
+
+ /** Cancel this pending step immediately, skipping any clean-up. */
+ public abstract void cancelImmediately();
+
+ /**
+ * Return the duration the vibrator was turned on when this step was played.
+ *
+ * @return A positive duration that the vibrator was turned on for by this step;
+ * Zero if the segment is not supported, the step was not played yet or vibrator was never
+ * turned on by this step; A negative value if the vibrator call has failed.
+ */
+ public long getVibratorOnDuration() {
+ return 0;
}
/**
@@ -452,6 +580,8 @@
public final CombinedVibration.Sequential sequentialEffect;
public final int currentIndex;
+ private long mVibratorsOnMaxDuration;
+
StartVibrateStep(CombinedVibration.Sequential effect) {
this(SystemClock.uptimeMillis() + effect.getDelays().get(0), effect, /* index= */ 0);
}
@@ -463,10 +593,15 @@
}
@Override
+ public long getVibratorOnDuration() {
+ return mVibratorsOnMaxDuration;
+ }
+
+ @Override
public List<Step> play() {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "StartVibrateStep");
List<Step> nextSteps = new ArrayList<>();
- long duration = -1;
+ mVibratorsOnMaxDuration = -1;
try {
if (DEBUG) {
Slog.d(TAG, "StartVibrateStep for effect #" + currentIndex);
@@ -478,25 +613,33 @@
return nextSteps;
}
- duration = startVibrating(effectMapping, nextSteps);
- noteVibratorOn(duration);
+ mVibratorsOnMaxDuration = startVibrating(effectMapping, nextSteps);
+ noteVibratorOn(mVibratorsOnMaxDuration);
} finally {
- if (duration < 0) {
- // Something failed while playing this step so stop playing this sequence.
- return EMPTY_STEP_LIST;
- }
- // It least one vibrator was started then add a finish step to wait for all
- // active vibrators to finish their individual steps before going to the next.
- // Otherwise this step was ignored so just go to the next one.
- Step nextStep = duration > 0 ? new FinishVibrateStep(this) : nextStep();
- if (nextStep != null) {
- nextSteps.add(nextStep);
+ if (mVibratorsOnMaxDuration >= 0) {
+ // It least one vibrator was started then add a finish step to wait for all
+ // active vibrators to finish their individual steps before going to the next.
+ // Otherwise this step was ignored so just go to the next one.
+ Step nextStep =
+ mVibratorsOnMaxDuration > 0 ? new FinishVibrateStep(this) : nextStep();
+ if (nextStep != null) {
+ nextSteps.add(nextStep);
+ }
}
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
return nextSteps;
}
+ @Override
+ public List<Step> cancel() {
+ return EMPTY_STEP_LIST;
+ }
+
+ @Override
+ public void cancelImmediately() {
+ }
+
/**
* Create the next {@link StartVibrateStep} to play this sequential effect, starting at the
* time this method is called, or null if sequence is complete.
@@ -593,7 +736,7 @@
// Some vibrator failed without being prepared so other vibrators might be
// active. Cancel and remove every pending step from output list.
for (int i = nextSteps.size() - 1; i >= 0; i--) {
- nextSteps.remove(i).cancel();
+ nextSteps.remove(i).cancelImmediately();
}
}
}
@@ -627,6 +770,12 @@
}
@Override
+ public boolean isCleanUp() {
+ // This step only notes that all the vibrators has been turned off.
+ return true;
+ }
+
+ @Override
public List<Step> play() {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "FinishVibrateStep");
try {
@@ -642,7 +791,13 @@
}
@Override
- public void cancel() {
+ public List<Step> cancel() {
+ cancelImmediately();
+ return EMPTY_STEP_LIST;
+ }
+
+ @Override
+ public void cancelImmediately() {
noteVibratorOff();
}
}
@@ -658,6 +813,7 @@
public final long vibratorOffTimeout;
long mVibratorOnResult;
+ boolean mVibratorCallbackReceived;
/**
* @param startTime The time to schedule this step in the {@link StepQueue}.
@@ -678,27 +834,28 @@
this.vibratorOffTimeout = vibratorOffTimeout;
}
- /**
- * Return the duration the vibrator was turned on when this step was played.
- *
- * @return A positive duration that the vibrator was turned on for by this step;
- * Zero if the segment is not supported, the step was not played yet or vibrator was never
- * turned on by this step; A negative value if the vibrator call has failed.
- */
+ @Override
public long getVibratorOnDuration() {
return mVibratorOnResult;
}
@Override
public boolean shouldPlayWhenVibratorComplete(int vibratorId) {
+ boolean isSameVibrator = controller.getVibratorInfo().getId() == vibratorId;
+ mVibratorCallbackReceived |= isSameVibrator;
// Only anticipate this step if a timeout was set to wait for the vibration to complete,
// otherwise we are waiting for the correct time to play the next step.
- return (controller.getVibratorInfo().getId() == vibratorId)
- && (vibratorOffTimeout > SystemClock.uptimeMillis());
+ return isSameVibrator && (vibratorOffTimeout > SystemClock.uptimeMillis());
}
@Override
- public void cancel() {
+ public List<Step> cancel() {
+ return Arrays.asList(new CompleteStep(SystemClock.uptimeMillis(),
+ /* cancelled= */ true, controller, vibratorOffTimeout));
+ }
+
+ @Override
+ public void cancelImmediately() {
if (vibratorOffTimeout > SystemClock.uptimeMillis()) {
// Vibrator might be running from previous steps, so turn it off while canceling.
stopVibrating();
@@ -712,6 +869,14 @@
controller.off();
}
+ void changeAmplitude(float amplitude) {
+ if (DEBUG) {
+ Slog.d(TAG, "Amplitude changed on vibrator " + controller.getVibratorInfo().getId()
+ + " to " + amplitude);
+ }
+ controller.setAmplitude(amplitude);
+ }
+
/** Return the {@link #nextVibrateStep} with same timings, only jumping the segments. */
public List<Step> skipToNextSteps(int segmentsSkipped) {
return nextSteps(startTime, vibratorOffTimeout, segmentsSkipped);
@@ -938,6 +1103,140 @@
}
/**
+ * Represents a step to complete a {@link VibrationEffect}.
+ *
+ * <p>This runs right at the time the vibration is considered to end and will update the pending
+ * vibrators count. This can turn off the vibrator or slowly ramp it down to zero amplitude.
+ */
+ private final class CompleteStep extends SingleVibratorStep {
+ private final boolean mCancelled;
+
+ CompleteStep(long startTime, boolean cancelled, VibratorController controller,
+ long vibratorOffTimeout) {
+ super(startTime, controller, /* effect= */ null, /* index= */ -1, vibratorOffTimeout);
+ mCancelled = cancelled;
+ }
+
+ @Override
+ public boolean isCleanUp() {
+ // If the vibration was cancelled then this is just a clean up to ramp off the vibrator.
+ // Otherwise this step is part of the vibration.
+ return mCancelled;
+ }
+
+ @Override
+ public List<Step> cancel() {
+ if (mCancelled) {
+ // Double cancelling will just turn off the vibrator right away.
+ return Arrays.asList(new OffStep(SystemClock.uptimeMillis(), controller));
+ }
+ return super.cancel();
+ }
+
+ @Override
+ public List<Step> play() {
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "CompleteStep");
+ try {
+ if (DEBUG) {
+ Slog.d(TAG, "Running " + (mCancelled ? "cancel" : "complete") + " vibration"
+ + " step on vibrator " + controller.getVibratorInfo().getId());
+ }
+ if (mVibratorCallbackReceived) {
+ // Vibration completion callback was received by this step, just turn if off
+ // and skip any clean-up.
+ stopVibrating();
+ return EMPTY_STEP_LIST;
+ }
+
+ float currentAmplitude = controller.getCurrentAmplitude();
+ long remainingOnDuration =
+ vibratorOffTimeout - CALLBACKS_EXTRA_TIMEOUT - SystemClock.uptimeMillis();
+ long rampDownDuration =
+ Math.min(remainingOnDuration, mVibrationSettings.getRampDownDuration());
+ long stepDownDuration = mVibrationSettings.getRampStepDuration();
+ if (currentAmplitude < RAMP_OFF_AMPLITUDE_MIN
+ || rampDownDuration <= stepDownDuration) {
+ // No need to ramp down the amplitude, just wait to turn it off.
+ if (mCancelled) {
+ // Vibration is completing because it was cancelled, turn off right away.
+ stopVibrating();
+ return EMPTY_STEP_LIST;
+ } else {
+ return Arrays.asList(new OffStep(vibratorOffTimeout, controller));
+ }
+ }
+
+ if (DEBUG) {
+ Slog.d(TAG, "Ramping down vibrator " + controller.getVibratorInfo().getId()
+ + " from amplitude " + currentAmplitude
+ + " for " + rampDownDuration + "ms");
+ }
+ float amplitudeDelta = currentAmplitude / (rampDownDuration / stepDownDuration);
+ float amplitudeTarget = currentAmplitude - amplitudeDelta;
+ long newVibratorOffTimeout = mCancelled ? rampDownDuration : vibratorOffTimeout;
+ return Arrays.asList(new RampOffStep(startTime, amplitudeTarget, amplitudeDelta,
+ controller, newVibratorOffTimeout));
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+ }
+ }
+ }
+
+ /** Represents a step to ramp down the vibrator amplitude before turning it off. */
+ private final class RampOffStep extends SingleVibratorStep {
+ private final float mAmplitudeTarget;
+ private final float mAmplitudeDelta;
+
+ RampOffStep(long startTime, float amplitudeTarget, float amplitudeDelta,
+ VibratorController controller, long vibratorOffTimeout) {
+ super(startTime, controller, /* effect= */ null, /* index= */ -1, vibratorOffTimeout);
+ mAmplitudeTarget = amplitudeTarget;
+ mAmplitudeDelta = amplitudeDelta;
+ }
+
+ @Override
+ public boolean isCleanUp() {
+ return true;
+ }
+
+ @Override
+ public List<Step> cancel() {
+ return Arrays.asList(new OffStep(SystemClock.uptimeMillis(), controller));
+ }
+
+ @Override
+ public List<Step> play() {
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "RampOffStep");
+ try {
+ if (DEBUG) {
+ long latency = SystemClock.uptimeMillis() - startTime;
+ Slog.d(TAG, "Ramp down the vibrator amplitude, step with "
+ + latency + "ms latency.");
+ }
+ if (mVibratorCallbackReceived) {
+ // Vibration completion callback was received by this step, just turn if off
+ // and skip the rest of the steps to ramp down the vibrator amplitude.
+ stopVibrating();
+ return EMPTY_STEP_LIST;
+ }
+
+ changeAmplitude(mAmplitudeTarget);
+
+ float newAmplitudeTarget = mAmplitudeTarget - mAmplitudeDelta;
+ if (newAmplitudeTarget < RAMP_OFF_AMPLITUDE_MIN) {
+ // Vibrator amplitude cannot go further down, just turn it off.
+ return Arrays.asList(new OffStep(vibratorOffTimeout, controller));
+ }
+ return Arrays.asList(new RampOffStep(
+ startTime + mVibrationSettings.getRampStepDuration(), newAmplitudeTarget,
+ mAmplitudeDelta, controller, vibratorOffTimeout));
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+ }
+ }
+ }
+
+ /**
* Represents a step to turn the vibrator off.
*
* <p>This runs after a timeout on the expected time the vibrator should have finished playing,
@@ -950,6 +1249,21 @@
}
@Override
+ public boolean isCleanUp() {
+ return true;
+ }
+
+ @Override
+ public List<Step> cancel() {
+ return Arrays.asList(new OffStep(SystemClock.uptimeMillis(), controller));
+ }
+
+ @Override
+ public void cancelImmediately() {
+ stopVibrating();
+ }
+
+ @Override
public List<Step> play() {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "OffStep");
try {
@@ -1044,14 +1358,6 @@
return controller.on(duration, mVibration.id);
}
- private void changeAmplitude(float amplitude) {
- if (DEBUG) {
- Slog.d(TAG, "Amplitude changed on vibrator " + controller.getVibratorInfo().getId()
- + " to " + amplitude);
- }
- controller.setAmplitude(amplitude);
- }
-
/**
* Get the duration the vibrator will be on for a waveform, starting at {@code startIndex}
* until the next time it's vibrating amplitude is zero or a different type of segment is
@@ -1080,6 +1386,11 @@
return 1000;
}
}
+ if (i == segmentCount && effect.getRepeatIndex() < 0) {
+ // Vibration ending at non-zero amplitude, add extra timings to ramp down after
+ // vibration is complete.
+ timing += mVibrationSettings.getRampDownDuration();
+ }
return timing;
}
}
diff --git a/services/core/java/com/android/server/vibrator/VibratorController.java b/services/core/java/com/android/server/vibrator/VibratorController.java
index 001d5c4..69cc90bf 100644
--- a/services/core/java/com/android/server/vibrator/VibratorController.java
+++ b/services/core/java/com/android/server/vibrator/VibratorController.java
@@ -54,6 +54,8 @@
private boolean mIsVibrating;
@GuardedBy("mLock")
private boolean mIsUnderExternalControl;
+ @GuardedBy("mLock")
+ private float mCurrentAmplitude;
/** Listener for vibration completion callbacks from native. */
public interface OnVibrationCompleteListener {
@@ -131,6 +133,23 @@
}
}
+ /**
+ * Returns the current amplitude the device is vibrating.
+ *
+ * <p>This value is set to 1 by the method {@link #on(long, long)}, and can be updated via
+ * {@link #setAmplitude(float)} if called while the device is vibrating.
+ *
+ * <p>If the device is vibrating via any other {@link #on} method then the current amplitude is
+ * unknown and this will return -1.
+ *
+ * <p>If {@link #isVibrating()} is false then this will be zero.
+ */
+ public float getCurrentAmplitude() {
+ synchronized (mLock) {
+ return mCurrentAmplitude;
+ }
+ }
+
/** Return {@code true} if this vibrator is under external control, false otherwise. */
public boolean isUnderExternalControl() {
synchronized (mLock) {
@@ -192,6 +211,9 @@
if (mVibratorInfo.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) {
mNativeWrapper.setAmplitude(amplitude);
}
+ if (mIsVibrating) {
+ mCurrentAmplitude = amplitude;
+ }
}
}
@@ -208,6 +230,7 @@
synchronized (mLock) {
long duration = mNativeWrapper.on(milliseconds, vibrationId);
if (duration > 0) {
+ mCurrentAmplitude = -1;
notifyVibratorOnLocked();
}
return duration;
@@ -228,6 +251,7 @@
long duration = mNativeWrapper.perform(prebaked.getEffectId(),
prebaked.getEffectStrength(), vibrationId);
if (duration > 0) {
+ mCurrentAmplitude = -1;
notifyVibratorOnLocked();
}
return duration;
@@ -250,6 +274,7 @@
synchronized (mLock) {
long duration = mNativeWrapper.compose(primitives, vibrationId);
if (duration > 0) {
+ mCurrentAmplitude = -1;
notifyVibratorOnLocked();
}
return duration;
@@ -272,6 +297,7 @@
int braking = mVibratorInfo.getDefaultBraking();
long duration = mNativeWrapper.composePwle(primitives, braking, vibrationId);
if (duration > 0) {
+ mCurrentAmplitude = -1;
notifyVibratorOnLocked();
}
return duration;
@@ -282,19 +308,23 @@
public void off() {
synchronized (mLock) {
mNativeWrapper.off();
+ mCurrentAmplitude = 0;
notifyVibratorOffLocked();
}
}
@Override
public String toString() {
- return "VibratorController{"
- + "mVibratorInfo=" + mVibratorInfo
- + ", mIsVibrating=" + mIsVibrating
- + ", mIsUnderExternalControl=" + mIsUnderExternalControl
- + ", mVibratorStateListeners count="
- + mVibratorStateListeners.getRegisteredCallbackCount()
- + '}';
+ synchronized (mLock) {
+ return "VibratorController{"
+ + "mVibratorInfo=" + mVibratorInfo
+ + ", mIsVibrating=" + mIsVibrating
+ + ", mCurrentAmplitude=" + mCurrentAmplitude
+ + ", mIsUnderExternalControl=" + mIsUnderExternalControl
+ + ", mVibratorStateListeners count="
+ + mVibratorStateListeners.getRegisteredCallbackCount()
+ + '}';
+ }
}
@GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index 644e451..fb8498e 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -514,8 +514,9 @@
return Vibration.Status.FORWARDED_TO_INPUT_DEVICES;
}
- VibrationThread vibThread = new VibrationThread(vib, mDeviceVibrationEffectAdapter,
- mVibrators, mWakeLock, mBatteryStatsService, mVibrationCallbacks);
+ VibrationThread vibThread = new VibrationThread(vib, mVibrationSettings,
+ mDeviceVibrationEffectAdapter, mVibrators, mWakeLock, mBatteryStatsService,
+ mVibrationCallbacks);
if (mCurrentVibration == null) {
return startVibrationThreadLocked(vibThread);
@@ -569,7 +570,6 @@
Trace.asyncTraceEnd(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
try {
Vibration vib = mCurrentVibration.getVibration();
- mCurrentVibration = null;
endVibrationLocked(vib, status);
finishAppOpModeLocked(vib.uid, vib.opPkg);
} finally {
@@ -613,7 +613,7 @@
// Repeating vibrations always take precedence.
return null;
}
- if (mCurrentVibration != null) {
+ if (mCurrentVibration != null && !mCurrentVibration.getVibration().hasEnded()) {
if (mCurrentVibration.getVibration().attrs.getUsage()
== VibrationAttributes.USAGE_ALARM) {
if (DEBUG) {
@@ -1003,20 +1003,29 @@
}
@Override
- public void onVibrationEnded(long vibrationId, Vibration.Status status) {
+ public void onVibrationCompleted(long vibrationId, Vibration.Status status) {
if (DEBUG) {
- Slog.d(TAG, "Vibration " + vibrationId + " thread finished with status " + status);
+ Slog.d(TAG, "Vibration " + vibrationId + " finished with status " + status);
}
synchronized (mLock) {
if (mCurrentVibration != null
&& mCurrentVibration.getVibration().id == vibrationId) {
reportFinishedVibrationLocked(status);
+ }
+ }
+ }
- if (mNextVibration != null) {
- VibrationThread vibThread = mNextVibration;
- mNextVibration = null;
- startVibrationThreadLocked(vibThread);
- }
+ @Override
+ public void onVibratorsReleased() {
+ if (DEBUG) {
+ Slog.d(TAG, "Vibrators released after finished vibration");
+ }
+ synchronized (mLock) {
+ mCurrentVibration = null;
+ if (mNextVibration != null) {
+ VibrationThread vibThread = mNextVibration;
+ mNextVibration = null;
+ startVibrationThreadLocked(vibThread);
}
}
}
@@ -1337,7 +1346,7 @@
// vibration that may be playing and ready the vibrator for external control.
if (mCurrentVibration != null) {
mNextVibration = null;
- mCurrentVibration.cancel();
+ mCurrentVibration.cancelImmediately();
cancelingVibration = mCurrentVibration;
}
} else {
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 26f475e..3a4faf7 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -1069,8 +1069,7 @@
}
}
- @Override
- public void restartActivityProcessIfVisible(IBinder token) {
+ void restartActivityProcessIfVisible(IBinder token) {
ActivityTaskManagerService.enforceTaskPermission("restartActivityProcess");
final long callingId = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index d551f66..64b5fc7 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -257,6 +257,7 @@
import android.content.LocusId;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -1929,12 +1930,23 @@
final TaskSnapshot snapshot =
mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, task.mUserId,
false /* restoreFromDisk */, false /* isLowResolution */);
- final int typeParameter = mWmService.mStartingSurfaceController
- .makeStartingWindowTypeParameter(newTask, taskSwitch, processRunning,
- allowTaskSnapshot, activityCreated, useEmpty);
final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
allowTaskSnapshot, activityCreated, snapshot);
+ //TODO(191787740) Remove for T
+ final boolean useLegacy = type == STARTING_WINDOW_TYPE_SPLASH_SCREEN
+ && mWmService.mStartingSurfaceController.isExceptionApp(packageName, mTargetSdk,
+ () -> {
+ ActivityInfo activityInfo = intent.resolveActivityInfo(
+ mAtmService.mContext.getPackageManager(),
+ PackageManager.GET_META_DATA);
+ return activityInfo != null ? activityInfo.applicationInfo : null;
+ });
+
+ final int typeParameter = mWmService.mStartingSurfaceController
+ .makeStartingWindowTypeParameter(newTask, taskSwitch, processRunning,
+ allowTaskSnapshot, activityCreated, useEmpty, useLegacy);
+
if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
if (isActivityTypeHome()) {
// The snapshot of home is only used once because it won't be updated while screen
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 680937b..090a01a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -302,6 +302,12 @@
// started or finished.
static final long ACTIVITY_BG_START_GRACE_PERIOD_MS = 10 * 1000;
+ /**
+ * The duration to keep a process in animating state (top scheduling group) when the
+ * wakefulness is changing from awake to doze or sleep.
+ */
+ private static final long DOZE_ANIMATING_STATE_RETAIN_TIME_MS = 2000;
+
/** Used to indicate that an app transition should be animated. */
static final boolean ANIMATE = true;
@@ -2758,12 +2764,35 @@
});
}
+ // The caller MUST NOT hold the global lock.
public void onScreenAwakeChanged(boolean isAwake) {
mH.post(() -> {
for (int i = mScreenObservers.size() - 1; i >= 0; i--) {
mScreenObservers.get(i).onAwakeStateChanged(isAwake);
}
});
+
+ if (isAwake) {
+ return;
+ }
+ // If the device is going to sleep, keep a higher priority temporarily for potential
+ // animation of system UI. Even if AOD is not enabled, it should be no harm.
+ final WindowProcessController proc;
+ synchronized (mGlobalLockWithoutBoost) {
+ final WindowState notificationShade = mRootWindowContainer.getDefaultDisplay()
+ .getDisplayPolicy().getNotificationShade();
+ proc = notificationShade != null
+ ? mProcessMap.getProcess(notificationShade.mSession.mPid) : null;
+ }
+ if (proc == null) {
+ return;
+ }
+ // Set to activity manager directly to make sure the state can be seen by the subsequent
+ // update of scheduling group.
+ proc.setRunningAnimationUnsafe();
+ mH.removeMessages(H.UPDATE_PROCESS_ANIMATING_STATE, proc);
+ mH.sendMessageDelayed(mH.obtainMessage(H.UPDATE_PROCESS_ANIMATING_STATE, proc),
+ DOZE_ANIMATING_STATE_RETAIN_TIME_MS);
}
@Override
@@ -5028,7 +5057,7 @@
final class H extends Handler {
static final int REPORT_TIME_TRACKER_MSG = 1;
-
+ static final int UPDATE_PROCESS_ANIMATING_STATE = 2;
static final int FIRST_ACTIVITY_TASK_MSG = 100;
static final int FIRST_SUPERVISOR_TASK_MSG = 200;
@@ -5045,6 +5074,13 @@
tracker.deliverResult(mContext);
}
break;
+ case UPDATE_PROCESS_ANIMATING_STATE: {
+ final WindowProcessController proc = (WindowProcessController) msg.obj;
+ synchronized (mGlobalLock) {
+ proc.updateRunningRemoteOrRecentsAnimation();
+ }
+ }
+ break;
}
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
index 2beb378..35add12 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
@@ -353,7 +353,7 @@
// Only update focus/visibility for the last one because there may be many root tasks are
// reparented and the intermediate states are unnecessary.
if (lastReparentedRootTask != null) {
- lastReparentedRootTask.postReparent();
+ lastReparentedRootTask.resumeNextFocusAfterReparent();
}
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 7d9971c..a72d9aa 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -5683,7 +5683,7 @@
// Only update focus/visibility for the last one because there may be many root tasks are
// reparented and the intermediate states are unnecessary.
if (lastReparentedRootTask != null) {
- lastReparentedRootTask.postReparent();
+ lastReparentedRootTask.resumeNextFocusAfterReparent();
}
releaseSelfIfNeeded();
mDisplayPolicy.release();
diff --git a/services/core/java/com/android/server/wm/DisplayHashController.java b/services/core/java/com/android/server/wm/DisplayHashController.java
index 0cf4379..64a5758 100644
--- a/services/core/java/com/android/server/wm/DisplayHashController.java
+++ b/services/core/java/com/android/server/wm/DisplayHashController.java
@@ -47,7 +47,6 @@
import android.os.Message;
import android.os.RemoteCallback;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.service.displayhash.DisplayHashParams;
import android.service.displayhash.DisplayHashingService;
import android.service.displayhash.IDisplayHashingService;
@@ -380,8 +379,7 @@
intent.setComponent(component);
final long token = Binder.clearCallingIdentity();
try {
- mContext.bindServiceAsUser(intent, mServiceConnection,
- Context.BIND_AUTO_CREATE, UserHandle.CURRENT);
+ mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
if (DEBUG) Slog.v(TAG, "bound");
} finally {
Binder.restoreCallingIdentity(token);
@@ -404,8 +402,15 @@
final Intent intent = new Intent(DisplayHashingService.SERVICE_INTERFACE);
intent.setPackage(packageName);
- final ResolveInfo resolveInfo = mContext.getPackageManager().resolveService(intent,
- PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+ final ResolveInfo resolveInfo;
+ final long token = Binder.clearCallingIdentity();
+ try {
+ resolveInfo = mContext.getPackageManager().resolveService(intent,
+ PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
if (resolveInfo == null || resolveInfo.serviceInfo == null) {
Slog.w(TAG, "No valid components found.");
return null;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 6242b97..9a6a518 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -66,7 +66,6 @@
import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityTaskSupervisor.dumpHistoryList;
import static com.android.server.wm.ActivityTaskSupervisor.printThisActivity;
-import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
import static com.android.server.wm.RootWindowContainerProto.IS_HOME_RECENTS_COMPONENT;
import static com.android.server.wm.RootWindowContainerProto.KEYGUARD_CONTROLLER;
import static com.android.server.wm.RootWindowContainerProto.WINDOW_CONTAINER;
@@ -2077,6 +2076,10 @@
+ " to its current taskDisplayArea=" + taskDisplayArea);
}
rootTask.reparent(taskDisplayArea, onTop);
+
+ // Resume focusable root task after reparenting to another display area.
+ rootTask.resumeNextFocusAfterReparent();
+
// TODO(multi-display): resize rootTasks properly if moved from split-screen.
}
diff --git a/services/core/java/com/android/server/wm/StartingSurfaceController.java b/services/core/java/com/android/server/wm/StartingSurfaceController.java
index da25747..45b53a1 100644
--- a/services/core/java/com/android/server/wm/StartingSurfaceController.java
+++ b/services/core/java/com/android/server/wm/StartingSurfaceController.java
@@ -18,6 +18,7 @@
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_LEGACY_SPLASH_SCREEN;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
@@ -85,7 +86,7 @@
int makeStartingWindowTypeParameter(boolean newTask, boolean taskSwitch,
boolean processRunning, boolean allowTaskSnapshot, boolean activityCreated,
- boolean useEmpty) {
+ boolean useEmpty, boolean useLegacy) {
int parameter = 0;
if (newTask) {
parameter |= TYPE_PARAMETER_NEW_TASK;
@@ -105,6 +106,9 @@
if (useEmpty) {
parameter |= TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN;
}
+ if (useLegacy) {
+ parameter |= TYPE_PARAMETER_LEGACY_SPLASH_SCREEN;
+ }
return parameter;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 136a5a1..777306a 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1464,12 +1464,6 @@
adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
mRootWindowContainer.updateUIDsPresentOnDisplay();
-
- // Resume next focusable root task after reparenting to another display if we aren't
- // removing the prevous display.
- if (oldDisplay != null && oldDisplay.isRemoving()) {
- postReparent();
- }
}
void cleanUpActivityReferences(ActivityRecord r) {
@@ -4114,9 +4108,6 @@
info.topActivityInfo = mReuseActivitiesReport.top != null
? mReuseActivitiesReport.top.info
: null;
- info.topActivityToken = mReuseActivitiesReport.top != null
- ? mReuseActivitiesReport.top.appToken
- : null;
// Whether the direct top activity is in size compat mode on foreground.
info.topActivityInSizeCompat = mReuseActivitiesReport.top != null
&& mReuseActivitiesReport.top.getOrganizedTask() == this
@@ -5462,8 +5453,7 @@
mRootWindowContainer.resumeFocusedTasksTopActivities();
}
- /** Resume next focusable root task after reparenting to another display. */
- void postReparent() {
+ void resumeNextFocusAfterReparent() {
adjustFocusToNextFocusableTask("reparent", true /* allowFocusSelf */,
true /* moveDisplayToTop */);
mRootWindowContainer.resumeFocusedTasksTopActivities();
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index abcb34c..2dc63ce 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -923,6 +923,34 @@
}
}
+ @Override
+ public void restartTaskTopActivityProcessIfVisible(WindowContainerToken token) {
+ enforceTaskPermission("restartTopActivityProcessIfVisible()");
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ final WindowContainer wc = WindowContainer.fromBinder(token.asBinder());
+ if (wc == null) {
+ Slog.w(TAG, "Could not resolve window from token");
+ return;
+ }
+ final Task task = wc.asTask();
+ if (task == null) {
+ Slog.w(TAG, "Could not resolve task from token");
+ return;
+ }
+ ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
+ "Restart top activity process of Task taskId=%d", task.mTaskId);
+ final ActivityRecord activity = task.getTopNonFinishingActivity();
+ if (activity != null) {
+ activity.restartProcessIfVisible();
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
public boolean handleInterceptBackPressedOnTaskRoot(Task task) {
if (task == null || !task.isOrganized()
|| !mInterceptBackPressedOnRootTasks.contains(task.mTaskId)) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 26cfbdf..1364c72 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -812,7 +812,9 @@
void updateNightModeForAllActivities(int nightMode) {
for (int i = mActivities.size() - 1; i >= 0; --i) {
final ActivityRecord r = mActivities.get(i);
- r.setOverrideNightMode(nightMode);
+ if (r.setOverrideNightMode(nightMode) && r.mVisibleRequested) {
+ r.ensureActivityConfiguration(0 /* globalChanges */, true /* preserveWindow */);
+ }
}
}
@@ -1594,14 +1596,18 @@
updateRunningRemoteOrRecentsAnimation();
}
- private void updateRunningRemoteOrRecentsAnimation() {
-
+ void updateRunningRemoteOrRecentsAnimation() {
// Posting on handler so WM lock isn't held when we call into AM.
mAtm.mH.sendMessage(PooledLambda.obtainMessage(
WindowProcessListener::setRunningRemoteAnimation, mListener,
mRunningRecentsAnimation || mRunningRemoteAnimation));
}
+ /** Adjusts scheduling group for animation. This method MUST NOT be called inside WM lock. */
+ void setRunningAnimationUnsafe() {
+ mListener.setRunningRemoteAnimation(true);
+ }
+
@Override
public String toString() {
return mOwner != null ? mOwner.toString() : null;
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index 7513512..3d4f866 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -131,28 +131,6 @@
return android::base::WriteFully(fd, &command, sizeof(command));
}
-static int waitForDataOrSignal(int fd, int event_fd) {
- struct pollfd pfds[2] = {{fd, POLLIN, 0}, {event_fd, POLLIN, 0}};
- // Wait until either data is ready or stop signal is received
- int res = poll(pfds, 2, PollTimeoutMs);
- if (res == -1 && errno == EINTR) {
- // Treat it the same as timeout and allow the caller to retry.
- return 0;
- }
- if (res <= 0) {
- return res;
- }
- // First check if there is a stop signal
- if (pfds[1].revents == POLLIN) {
- return event_fd;
- }
- // Otherwise check if incoming data is ready
- if (pfds[0].revents == POLLIN) {
- return fd;
- }
- return -1;
-}
-
static bool readChunk(int fd, std::vector<uint8_t>& data) {
int32_t size;
if (!android::base::ReadFully(fd, &size, sizeof(size))) {
@@ -382,7 +360,12 @@
class PMSCDataLoader : public android::dataloader::DataLoader {
public:
PMSCDataLoader(JavaVM* jvm) : mJvm(jvm) { CHECK(mJvm); }
- ~PMSCDataLoader() { onTraceChanged().unregisterCallback(this); }
+ ~PMSCDataLoader() {
+ onTraceChanged().unregisterCallback(this);
+ if (mReceiverThread.joinable()) {
+ mReceiverThread.join();
+ }
+ }
void updateReadLogsState(const bool enabled) {
if (enabled != mReadLogsEnabled.exchange(enabled)) {
@@ -417,11 +400,7 @@
mReceiverThread.join();
}
}
- void onDestroy() final {
- onTraceChanged().unregisterCallback(this);
- // Make sure the receiver thread stopped.
- CHECK(!mReceiverThread.joinable());
- }
+ void onDestroy() final {}
// Installation.
bool onPrepareImage(dataloader::DataLoaderInstallationFiles addedFiles) final {
@@ -573,6 +552,60 @@
return true;
}
+ enum class WaitResult {
+ DataAvailable,
+ Timeout,
+ Failure,
+ StopRequested,
+ };
+
+ WaitResult waitForData(int fd) {
+ using Clock = std::chrono::steady_clock;
+ using Milliseconds = std::chrono::milliseconds;
+
+ auto pollTimeoutMs = PollTimeoutMs;
+ const auto waitEnd = Clock::now() + Milliseconds(pollTimeoutMs);
+ while (!mStopReceiving) {
+ struct pollfd pfds[2] = {{fd, POLLIN, 0}, {mEventFd, POLLIN, 0}};
+ // Wait until either data is ready or stop signal is received
+ int res = poll(pfds, std::size(pfds), pollTimeoutMs);
+
+ if (res < 0) {
+ if (errno == EINTR) {
+ pollTimeoutMs = std::chrono::duration_cast<Milliseconds>(waitEnd - Clock::now())
+ .count();
+ if (pollTimeoutMs < 0) {
+ return WaitResult::Timeout;
+ }
+ continue;
+ }
+ ALOGE("Failed to poll. Error %d", errno);
+ return WaitResult::Failure;
+ }
+
+ if (res == 0) {
+ return WaitResult::Timeout;
+ }
+
+ // First check if there is a stop signal
+ if (pfds[1].revents == POLLIN) {
+ ALOGE("DataLoader requested to stop.");
+ return WaitResult::StopRequested;
+ }
+ // Otherwise check if incoming data is ready
+ if (pfds[0].revents == POLLIN) {
+ return WaitResult::DataAvailable;
+ }
+
+ // Invalid case, just fail.
+ ALOGE("Failed to poll. Result %d", res);
+ return WaitResult::Failure;
+ }
+
+ ALOGE("DataLoader requested to stop.");
+ return WaitResult::StopRequested;
+ }
+
// Streaming.
bool initStreaming(unique_fd inout, MetadataMode mode) {
mEventFd.reset(eventfd(0, EFD_CLOEXEC));
@@ -582,6 +615,11 @@
}
// Awaiting adb handshake.
+ if (waitForData(inout) != WaitResult::DataAvailable) {
+ ALOGE("Failure waiting for the handshake.");
+ return false;
+ }
+
char okay_buf[OKAY.size()];
if (!android::base::ReadFully(inout, okay_buf, OKAY.size())) {
ALOGE("Failed to receive OKAY. Abort. Error %d", errno);
@@ -601,8 +639,14 @@
}
}
+ if (mStopReceiving) {
+ ALOGE("DataLoader requested to stop.");
+ return false;
+ }
+
mReceiverThread = std::thread(
[this, io = std::move(inout), mode]() mutable { receiver(std::move(io), mode); });
+
ALOGI("Started streaming...");
return true;
}
@@ -750,17 +794,16 @@
std::vector<IncFsDataBlock> instructions;
std::unordered_map<FileIdx, unique_fd> writeFds;
while (!mStopReceiving) {
- const int res = waitForDataOrSignal(inout, mEventFd);
- if (res == 0) {
+ const auto res = waitForData(inout);
+ if (res == WaitResult::Timeout) {
continue;
}
- if (res < 0) {
- ALOGE("Failed to poll. Abort. Error %d", res);
+ if (res == WaitResult::Failure) {
mStatusListener->reportStatus(DATA_LOADER_UNRECOVERABLE);
break;
}
- if (res == mEventFd) {
- ALOGE("DataLoader requested to stop. Sending EXIT to server.");
+ if (res == WaitResult::StopRequested) {
+ ALOGE("Sending EXIT to server.");
sendRequest(inout, EXIT);
break;
}
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index 82aaa61..429edf1 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -81,6 +81,16 @@
<xs:annotation name="nullable"/>
<xs:annotation name="final"/>
</xs:element>
+ <!-- The highest (most severe) thermal status at which high-brightness-mode is allowed
+ to operate. -->
+ <xs:element name="thermalStatusLimit" type="thermalStatus" minOccurs="0" maxOccurs="1">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
+ <xs:element name="allowInLowPowerMode" type="xs:boolean" minOccurs="0" maxOccurs="1">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
</xs:all>
<xs:attribute name="enabled" type="xs:boolean" use="optional"/>
</xs:complexType>
@@ -102,6 +112,19 @@
</xs:all>
</xs:complexType>
+ <!-- Maps to PowerManager.THERMAL_STATUS_* values. -->
+ <xs:simpleType name="thermalStatus">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="none"/>
+ <xs:enumeration value="light"/>
+ <xs:enumeration value="moderate"/>
+ <xs:enumeration value="severe"/>
+ <xs:enumeration value="critical"/>
+ <xs:enumeration value="emergency"/>
+ <xs:enumeration value="shutdown"/>
+ </xs:restriction>
+ </xs:simpleType>
+
<xs:complexType name="nitsMap">
<xs:sequence>
<xs:element name="point" type="point" maxOccurs="unbounded" minOccurs="2">
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index 6e2e362..ad18602 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -42,14 +42,18 @@
public class HighBrightnessMode {
ctor public HighBrightnessMode();
+ method @NonNull public final boolean getAllowInLowPowerMode_all();
method public boolean getEnabled();
method @NonNull public final java.math.BigDecimal getMinimumLux_all();
method @Nullable public final com.android.server.display.config.RefreshRateRange getRefreshRate_all();
+ method @NonNull public final com.android.server.display.config.ThermalStatus getThermalStatusLimit_all();
method public com.android.server.display.config.HbmTiming getTiming_all();
method @NonNull public final java.math.BigDecimal getTransitionPoint_all();
+ method public final void setAllowInLowPowerMode_all(@NonNull boolean);
method public void setEnabled(boolean);
method public final void setMinimumLux_all(@NonNull java.math.BigDecimal);
method public final void setRefreshRate_all(@Nullable com.android.server.display.config.RefreshRateRange);
+ method public final void setThermalStatusLimit_all(@NonNull com.android.server.display.config.ThermalStatus);
method public void setTiming_all(com.android.server.display.config.HbmTiming);
method public final void setTransitionPoint_all(@NonNull java.math.BigDecimal);
}
@@ -85,6 +89,17 @@
method public final void setType(@Nullable String);
}
+ public enum ThermalStatus {
+ method public String getRawName();
+ enum_constant public static final com.android.server.display.config.ThermalStatus critical;
+ enum_constant public static final com.android.server.display.config.ThermalStatus emergency;
+ enum_constant public static final com.android.server.display.config.ThermalStatus light;
+ enum_constant public static final com.android.server.display.config.ThermalStatus moderate;
+ enum_constant public static final com.android.server.display.config.ThermalStatus none;
+ enum_constant public static final com.android.server.display.config.ThermalStatus severe;
+ enum_constant public static final com.android.server.display.config.ThermalStatus shutdown;
+ }
+
public class XmlParser {
ctor public XmlParser();
method public static com.android.server.display.config.DisplayConfiguration read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
diff --git a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java
index 4c5bbeb..2cd20c5 100644
--- a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java
+++ b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java
@@ -208,6 +208,24 @@
@NonNull RecognitionRequest recognitionRequest,
IMusicRecognitionManagerCallback clientCallback,
ParcelFileDescriptor audioSink) {
+ int maxAudioLengthSeconds = Math.min(recognitionRequest.getMaxAudioLengthSeconds(),
+ MAX_STREAMING_SECONDS);
+ if (maxAudioLengthSeconds <= 0) {
+ // TODO(b/192992319): A request to stream 0s of audio can be used to initialize the
+ // music recognition service implementation, hence not reporting an error here.
+ // The TODO for Android T is to move this functionality into an init() API call.
+ Slog.i(TAG, "No audio requested. Closing stream.");
+ try {
+ audioSink.close();
+ clientCallback.onAudioStreamClosed();
+ } catch (IOException e) {
+ Slog.e(TAG, "Problem closing stream.", e);
+ } catch (RemoteException ignored) {
+ // Ignored.
+ }
+ return;
+ }
+
try {
startRecordAudioOp(attributionTag);
} catch (SecurityException e) {
@@ -224,8 +242,6 @@
return;
}
- int maxAudioLengthSeconds = Math.min(recognitionRequest.getMaxAudioLengthSeconds(),
- MAX_STREAMING_SECONDS);
AudioRecord audioRecord = createAudioRecord(recognitionRequest, maxAudioLengthSeconds);
try (OutputStream fos =
new ParcelFileDescriptor.AutoCloseOutputStream(audioSink)) {
diff --git a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
index 8e4cdc9..fbcf53d 100644
--- a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
@@ -20,22 +20,43 @@
import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT;
import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.content.Context;
+import android.content.ContextWrapper;
import android.os.Binder;
import android.os.Handler;
+import android.os.IThermalEventListener;
+import android.os.IThermalService;
import android.os.Message;
+import android.os.PowerManager;
+import android.os.Temperature;
+import android.os.Temperature.ThrottlingStatus;
import android.os.test.TestLooper;
import android.platform.test.annotations.Presubmit;
+import android.test.mock.MockContentResolver;
+import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.internal.util.test.FakeSettingsProviderRule;
import com.android.server.display.DisplayDeviceConfig.HighBrightnessModeData;
+import com.android.server.display.HighBrightnessModeController.Injector;
import com.android.server.testutils.OffsettableClock;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
@SmallTest
@Presubmit
@@ -47,6 +68,8 @@
private static final long TIME_WINDOW_MILLIS = 55 * 1000;
private static final long TIME_ALLOWED_IN_WINDOW_MILLIS = 12 * 1000;
private static final long TIME_MINIMUM_AVAILABLE_TO_ENABLE_MILLIS = 5 * 1000;
+ private static final int THERMAL_STATUS_LIMIT = PowerManager.THERMAL_STATUS_SEVERE;
+ private static final boolean ALLOW_IN_LOW_POWER_MODE = false;
private static final float DEFAULT_MIN = 0.01f;
private static final float DEFAULT_MAX = 0.80f;
@@ -57,22 +80,30 @@
private TestLooper mTestLooper;
private Handler mHandler;
private Binder mDisplayToken;
+ private Context mContextSpy;
+
+ @Rule
+ public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
+
+ @Mock IThermalService mThermalServiceMock;
+ @Mock Injector mInjectorMock;
+
+ @Captor ArgumentCaptor<IThermalEventListener> mThermalEventListenerCaptor;
private static final HighBrightnessModeData DEFAULT_HBM_DATA =
new HighBrightnessModeData(MINIMUM_LUX, TRANSITION_POINT, TIME_WINDOW_MILLIS,
- TIME_ALLOWED_IN_WINDOW_MILLIS, TIME_MINIMUM_AVAILABLE_TO_ENABLE_MILLIS);
+ TIME_ALLOWED_IN_WINDOW_MILLIS, TIME_MINIMUM_AVAILABLE_TO_ENABLE_MILLIS,
+ THERMAL_STATUS_LIMIT, ALLOW_IN_LOW_POWER_MODE);
@Before
public void setUp() {
- mClock = new OffsettableClock.Stopped();
- mTestLooper = new TestLooper(mClock::now);
+ MockitoAnnotations.initMocks(this);
mDisplayToken = null;
- mHandler = new Handler(mTestLooper.getLooper(), new Handler.Callback() {
- @Override
- public boolean handleMessage(Message msg) {
- return true;
- }
- });
+ mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
+ final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
+ when(mContextSpy.getContentResolver()).thenReturn(resolver);
+
+ when(mInjectorMock.getThermalService()).thenReturn(mThermalServiceMock);
}
/////////////////
@@ -81,15 +112,19 @@
@Test
public void testNoHbmData() {
+ initHandler(null);
final HighBrightnessModeController hbmc = new HighBrightnessModeController(
- mClock::now, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {});
+ mInjectorMock, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null,
+ () -> {}, mContextSpy);
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
}
@Test
public void testNoHbmData_Enabled() {
+ initHandler(null);
final HighBrightnessModeController hbmc = new HighBrightnessModeController(
- mClock::now, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {});
+ mInjectorMock, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null,
+ () -> {}, mContextSpy);
hbmc.setAutoBrightnessEnabled(true);
hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
@@ -258,6 +293,54 @@
assertState(hbmc, DEFAULT_MIN, TRANSITION_POINT, HIGH_BRIGHTNESS_MODE_OFF);
}
+ @Test
+ public void testNoHbmInHighThermalState() throws Exception {
+ final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock());
+
+ verify(mThermalServiceMock).registerThermalEventListenerWithType(
+ mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_SKIN));
+ final IThermalEventListener listener = mThermalEventListenerCaptor.getValue();
+
+ // Set the thermal status too high.
+ listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_CRITICAL));
+
+ // Try to go into HBM mode but fail
+ hbmc.setAutoBrightnessEnabled(true);
+ hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
+ advanceTime(10);
+
+ assertEquals(HIGH_BRIGHTNESS_MODE_OFF, hbmc.getHighBrightnessMode());
+ }
+
+ @Test
+ public void testHbmTurnsOffInHighThermalState() throws Exception {
+ final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock());
+
+ verify(mThermalServiceMock).registerThermalEventListenerWithType(
+ mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_SKIN));
+ final IThermalEventListener listener = mThermalEventListenerCaptor.getValue();
+
+ // Set the thermal status tolerable
+ listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_LIGHT));
+
+ // Try to go into HBM mode
+ hbmc.setAutoBrightnessEnabled(true);
+ hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
+ advanceTime(1);
+
+ assertEquals(HIGH_BRIGHTNESS_MODE_SUNLIGHT, hbmc.getHighBrightnessMode());
+
+ // Set the thermal status too high and verify we're off.
+ listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_CRITICAL));
+ advanceTime(10);
+ assertEquals(HIGH_BRIGHTNESS_MODE_OFF, hbmc.getHighBrightnessMode());
+
+ // Set the thermal status low again and verify we're back on.
+ listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_SEVERE));
+ advanceTime(1);
+ assertEquals(HIGH_BRIGHTNESS_MODE_SUNLIGHT, hbmc.getHighBrightnessMode());
+ }
+
private void assertState(HighBrightnessModeController hbmc,
float brightnessMin, float brightnessMax, int hbmMode) {
assertEquals(brightnessMin, hbmc.getCurrentBrightnessMin(), EPSILON);
@@ -265,14 +348,35 @@
assertEquals(hbmMode, hbmc.getHighBrightnessMode());
}
- // Creates instance with standard initialization values.
private HighBrightnessModeController createDefaultHbm() {
- return new HighBrightnessModeController(mClock::now, mHandler, mDisplayToken, DEFAULT_MIN,
- DEFAULT_MAX, DEFAULT_HBM_DATA, () -> {});
+ return createDefaultHbm(null);
+ }
+
+ // Creates instance with standard initialization values.
+ private HighBrightnessModeController createDefaultHbm(OffsettableClock clock) {
+ initHandler(clock);
+ return new HighBrightnessModeController(mInjectorMock, mHandler, mDisplayToken, DEFAULT_MIN,
+ DEFAULT_MAX, DEFAULT_HBM_DATA, () -> {}, mContextSpy);
+ }
+
+ private void initHandler(OffsettableClock clock) {
+ mClock = clock != null ? clock : new OffsettableClock.Stopped();
+ when(mInjectorMock.getClock()).thenReturn(mClock::now);
+ mTestLooper = new TestLooper(mClock::now);
+ mHandler = new Handler(mTestLooper.getLooper(), new Handler.Callback() {
+ @Override
+ public boolean handleMessage(Message msg) {
+ return true;
+ }
+ });
}
private void advanceTime(long timeMs) {
mClock.fastForward(timeMs);
mTestLooper.dispatchAll();
}
+
+ private Temperature getSkinTemp(@ThrottlingStatus int status) {
+ return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java
index aaf40d7..397770b 100644
--- a/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java
@@ -26,6 +26,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyLong;
@@ -36,6 +37,7 @@
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
@@ -43,6 +45,7 @@
import android.os.Process;
import com.android.server.FgThread;
+import com.android.server.LocalServices;
import com.android.server.power.hint.HintManagerService.AppHintSession;
import com.android.server.power.hint.HintManagerService.Injector;
import com.android.server.power.hint.HintManagerService.NativeWrapper;
@@ -74,6 +77,7 @@
@Mock private Context mContext;
@Mock private HintManagerService.NativeWrapper mNativeWrapperMock;
+ @Mock private ActivityManagerInternal mAmInternalMock;
private HintManagerService mService;
@@ -86,6 +90,9 @@
eq(DEFAULT_TARGET_DURATION))).thenReturn(1L);
when(mNativeWrapperMock.halCreateHintSession(eq(TGID), eq(UID), eq(SESSION_TIDS_B),
eq(DEFAULT_TARGET_DURATION))).thenReturn(2L);
+ when(mAmInternalMock.getIsolatedProcesses(anyInt())).thenReturn(null);
+ LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+ LocalServices.addService(ActivityManagerInternal.class, mAmInternalMock);
}
private HintManagerService createService() {
@@ -105,6 +112,17 @@
}
@Test
+ public void testCreateHintSessionInvalidPid() throws Exception {
+ HintManagerService service = createService();
+ IBinder token = new Binder();
+ // Make sure we throw exception when adding a TID doesn't belong to the processes
+ // In this case, we add `init` PID into the list.
+ assertThrows(SecurityException.class,
+ () -> service.getBinderServiceInstance().createHintSession(token,
+ new int[]{TID, 1}, DEFAULT_TARGET_DURATION));
+ }
+
+ @Test
public void testCreateHintSession() throws Exception {
HintManagerService service = createService();
IBinder token = new Binder();
diff --git a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java
index 614949c..69f0065 100644
--- a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java
@@ -292,23 +292,29 @@
intent.setClipData(clip);
{
- // When granting towards primary, persistable can't be honored so
- // the entire grant fails
- try {
- mService.checkGrantUriPermissionFromIntent(
- intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY);
- fail();
- } catch (SecurityException expected) {
+ // The camera package shouldn't be able to see other packages or their providers,
+ // so make sure the grant only succeeds for the camera's URIs.
+ final NeededUriGrants nug = mService.checkGrantUriPermissionFromIntent(
+ intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY);
+ if (nug != null && nug.uris != null) {
+ for (GrantUri gu : nug.uris) {
+ if (!gu.uri.getAuthority().equals(PKG_CAMERA)) {
+ fail();
+ }
+ }
}
}
{
- // When granting towards secondary, persistable can't be honored so
- // the entire grant fails
- try {
- mService.checkGrantUriPermissionFromIntent(
- intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_SECONDARY);
- fail();
- } catch (SecurityException expected) {
+ // The camera package shouldn't be able to see other packages or their providers,
+ // so make sure the grant only succeeds for the camera's URIs.
+ final NeededUriGrants nug = mService.checkGrantUriPermissionFromIntent(
+ intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_SECONDARY);
+ if (nug != null && nug.uris != null) {
+ for (GrantUri gu : nug.uris) {
+ if (!gu.uri.getAuthority().equals(PKG_CAMERA)) {
+ fail();
+ }
+ }
}
}
}
diff --git a/services/tests/servicestests/src/com/android/server/uri/UriGrantsMockContext.java b/services/tests/servicestests/src/com/android/server/uri/UriGrantsMockContext.java
index 2c719ff..a6307b3 100644
--- a/services/tests/servicestests/src/com/android/server/uri/UriGrantsMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/uri/UriGrantsMockContext.java
@@ -135,14 +135,29 @@
when(mPmInternal.resolveContentProvider(eq(PKG_CAMERA), anyInt(), eq(userId)))
.thenReturn(buildCameraProvider(userId));
+ when(mPmInternal.resolveContentProvider(eq(PKG_CAMERA), anyInt(), eq(userId),
+ eq(UserHandle.getUid(userId, UID_CAMERA))))
+ .thenReturn(buildCameraProvider(userId));
when(mPmInternal.resolveContentProvider(eq(PKG_PRIVATE), anyInt(), eq(userId)))
.thenReturn(buildPrivateProvider(userId));
+ when(mPmInternal.resolveContentProvider(eq(PKG_PRIVATE), anyInt(), eq(userId),
+ eq(UserHandle.getUid(userId, UID_PRIVATE))))
+ .thenReturn(buildPrivateProvider(userId));
when(mPmInternal.resolveContentProvider(eq(PKG_PUBLIC), anyInt(), eq(userId)))
.thenReturn(buildPublicProvider(userId));
+ when(mPmInternal.resolveContentProvider(eq(PKG_PUBLIC), anyInt(), eq(userId),
+ eq(UserHandle.getUid(userId, UID_PUBLIC))))
+ .thenReturn(buildPublicProvider(userId));
when(mPmInternal.resolveContentProvider(eq(PKG_FORCE), anyInt(), eq(userId)))
.thenReturn(buildForceProvider(userId));
+ when(mPmInternal.resolveContentProvider(eq(PKG_FORCE), anyInt(), eq(userId),
+ eq(UserHandle.getUid(userId, UID_FORCE))))
+ .thenReturn(buildForceProvider(userId));
when(mPmInternal.resolveContentProvider(eq(PKG_COMPLEX), anyInt(), eq(userId)))
.thenReturn(buildComplexProvider(userId));
+ when(mPmInternal.resolveContentProvider(eq(PKG_COMPLEX), anyInt(), eq(userId),
+ eq(UserHandle.getUid(userId, UID_COMPLEX))))
+ .thenReturn(buildComplexProvider(userId));
}
}
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
index 6d25e8c..1596483 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
@@ -27,6 +27,7 @@
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -86,6 +87,7 @@
private static final int VIBRATOR_ID = 1;
private static final String PACKAGE_NAME = "package";
private static final VibrationAttributes ATTRS = new VibrationAttributes.Builder().build();
+ private static final int TEST_RAMP_STEP_DURATION = 5;
@Rule
public MockitoRule mMockitoRule = MockitoJUnit.rule();
@@ -100,6 +102,7 @@
private IBatteryStats mIBatteryStatsMock;
private final Map<Integer, FakeVibratorControllerProvider> mVibratorProviders = new HashMap<>();
+ private VibrationSettings mVibrationSettings;
private DeviceVibrationEffectAdapter mEffectAdapter;
private PowerManager.WakeLock mWakeLock;
private TestLooper mTestLooper;
@@ -109,9 +112,9 @@
mTestLooper = new TestLooper();
Context context = InstrumentationRegistry.getContext();
- VibrationSettings vibrationSettings = new VibrationSettings(context,
- new Handler(mTestLooper.getLooper()));
- mEffectAdapter = new DeviceVibrationEffectAdapter(vibrationSettings);
+ mVibrationSettings = new VibrationSettings(context, new Handler(mTestLooper.getLooper()),
+ /* rampDownDuration= */ 0, TEST_RAMP_STEP_DURATION);
+ mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
mWakeLock = context.getSystemService(
PowerManager.class).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*");
@@ -128,8 +131,7 @@
waitForCompletion(thread);
verify(mControllerCallbacks, never()).onComplete(anyInt(), eq(vibrationId));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId),
- eq(Vibration.Status.IGNORED_UNSUPPORTED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.IGNORED_UNSUPPORTED);
}
@Test
@@ -143,8 +145,7 @@
waitForCompletion(thread);
verify(mControllerCallbacks, never()).onComplete(anyInt(), eq(vibrationId));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId),
- eq(Vibration.Status.IGNORED_UNSUPPORTED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.IGNORED_UNSUPPORTED);
}
@Test
@@ -159,7 +160,7 @@
verify(mIBatteryStatsMock).noteVibratorOn(eq(UID), eq(10L));
verify(mIBatteryStatsMock).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(10)),
@@ -178,7 +179,7 @@
verify(mIBatteryStatsMock).noteVibratorOn(eq(UID), eq(10L));
verify(mIBatteryStatsMock).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(10)),
@@ -200,7 +201,7 @@
verify(mIBatteryStatsMock).noteVibratorOn(eq(UID), eq(15L));
verify(mIBatteryStatsMock).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(15)),
@@ -232,7 +233,7 @@
verify(mIBatteryStatsMock).noteVibratorOn(eq(UID), anyLong());
verify(mIBatteryStatsMock).noteVibratorOff(eq(UID));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.CANCELLED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
List<Float> playedAmplitudes = fakeVibrator.getAmplitudes();
@@ -269,7 +270,7 @@
waitForCompletion(vibrationThread, /* timeout= */ 50);
waitForCompletion(cancellingThread);
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.CANCELLED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
assertFalse(vibrationThread.getVibrators().get(VIBRATOR_ID).isVibrating());
}
@@ -294,7 +295,7 @@
waitForCompletion(vibrationThread, /* timeout= */ 50);
waitForCompletion(cancellingThread);
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.CANCELLED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
assertFalse(vibrationThread.getVibrators().get(VIBRATOR_ID).isVibrating());
}
@@ -310,7 +311,7 @@
verify(mIBatteryStatsMock).noteVibratorOn(eq(UID), eq(20L));
verify(mIBatteryStatsMock).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_THUD)),
@@ -333,7 +334,7 @@
verify(mIBatteryStatsMock).noteVibratorOn(eq(UID), eq(10L));
verify(mIBatteryStatsMock).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedOneShot(10)),
@@ -352,8 +353,7 @@
verify(mIBatteryStatsMock, never()).noteVibratorOn(eq(UID), anyLong());
verify(mIBatteryStatsMock, never()).noteVibratorOff(eq(UID));
verify(mControllerCallbacks, never()).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId),
- eq(Vibration.Status.IGNORED_UNSUPPORTED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.IGNORED_UNSUPPORTED);
assertTrue(mVibratorProviders.get(VIBRATOR_ID).getEffectSegments().isEmpty());
}
@@ -373,7 +373,7 @@
verify(mIBatteryStatsMock).noteVibratorOn(eq(UID), eq(40L));
verify(mIBatteryStatsMock).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(
expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 0),
@@ -393,8 +393,7 @@
verify(mIBatteryStatsMock, never()).noteVibratorOn(eq(UID), anyLong());
verify(mIBatteryStatsMock, never()).noteVibratorOff(eq(UID));
verify(mControllerCallbacks, never()).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId),
- eq(Vibration.Status.IGNORED_UNSUPPORTED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.IGNORED_UNSUPPORTED);
assertTrue(mVibratorProviders.get(VIBRATOR_ID).getEffectSegments().isEmpty());
}
@@ -413,7 +412,7 @@
VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
waitForCompletion(thread);
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
// Vibrator compose called twice.
verify(mControllerCallbacks, times(2)).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
assertEquals(3, fakeVibrator.getEffectSegments().size());
@@ -443,7 +442,7 @@
verify(mIBatteryStatsMock).noteVibratorOn(eq(UID), eq(10L));
verify(mIBatteryStatsMock).noteVibratorOff(eq(UID));
verify(mControllerCallbacks, times(4)).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(
expectedOneShot(10),
@@ -479,7 +478,7 @@
verify(mIBatteryStatsMock).noteVibratorOn(eq(UID), eq(100L));
verify(mIBatteryStatsMock).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(
expectedRamp(/* amplitude= */ 1, /* frequency= */ 150, /* duration= */ 10),
@@ -512,7 +511,7 @@
VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
waitForCompletion(thread);
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
// Vibrator compose called twice.
verify(mControllerCallbacks, times(2)).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
assertEquals(4, fakeVibrator.getEffectSegments().size());
@@ -537,7 +536,7 @@
waitForCompletion(thread);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.CANCELLED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
}
@Test
@@ -545,10 +544,10 @@
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
long vibrationId = 1;
- waitForCompletion(startThreadAndDispatcher(vibrationId++,
+ waitForCompletion(startThreadAndDispatcher(vibrationId,
VibrationEffect.createOneShot(10, 100)));
- verify(mThreadCallbacks).onVibrationEnded(anyLong(), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
verify(mThreadCallbacks, never()).prepareSyncedVibration(anyLong(), any());
verify(mThreadCallbacks, never()).triggerSyncedVibration(anyLong());
verify(mThreadCallbacks, never()).cancelSyncedVibration();
@@ -571,7 +570,7 @@
verify(mIBatteryStatsMock).noteVibratorOff(eq(UID));
verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
verify(mControllerCallbacks, never()).onComplete(eq(2), eq(vibrationId));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_TICK)),
@@ -596,7 +595,7 @@
verify(mControllerCallbacks).onComplete(eq(1), eq(vibrationId));
verify(mControllerCallbacks).onComplete(eq(2), eq(vibrationId));
verify(mControllerCallbacks).onComplete(eq(3), eq(vibrationId));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(1).isVibrating());
assertFalse(thread.getVibrators().get(2).isVibrating());
assertFalse(thread.getVibrators().get(3).isVibrating());
@@ -635,7 +634,7 @@
verify(mControllerCallbacks).onComplete(eq(2), eq(vibrationId));
verify(mControllerCallbacks).onComplete(eq(3), eq(vibrationId));
verify(mControllerCallbacks).onComplete(eq(4), eq(vibrationId));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(1).isVibrating());
assertFalse(thread.getVibrators().get(2).isVibrating());
assertFalse(thread.getVibrators().get(3).isVibrating());
@@ -686,7 +685,7 @@
batterVerifier.verify(mIBatteryStatsMock).noteVibratorOn(eq(UID), eq(20L));
batterVerifier.verify(mIBatteryStatsMock).noteVibratorOff(eq(UID));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(1).isVibrating());
assertFalse(thread.getVibrators().get(2).isVibrating());
assertFalse(thread.getVibrators().get(3).isVibrating());
@@ -727,7 +726,7 @@
verify(mThreadCallbacks).prepareSyncedVibration(eq(expectedCap), eq(vibratorIds));
verify(mThreadCallbacks).triggerSyncedVibration(eq(vibrationId));
verify(mThreadCallbacks, never()).cancelSyncedVibration();
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
VibrationEffectSegment expected = expectedPrimitive(
VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 100);
@@ -767,7 +766,7 @@
verify(mThreadCallbacks).prepareSyncedVibration(eq(expectedCap), eq(vibratorIds));
verify(mThreadCallbacks).triggerSyncedVibration(eq(vibrationId));
verify(mThreadCallbacks, never()).cancelSyncedVibration();
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
}
@Test
@@ -858,7 +857,7 @@
verify(mControllerCallbacks).onComplete(eq(1), eq(vibrationId));
verify(mControllerCallbacks).onComplete(eq(2), eq(vibrationId));
verify(mControllerCallbacks).onComplete(eq(3), eq(vibrationId));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(1).isVibrating());
assertFalse(thread.getVibrators().get(2).isVibrating());
assertFalse(thread.getVibrators().get(3).isVibrating());
@@ -935,7 +934,7 @@
// After the vibrator call ends the vibration is cancelled and the vibrator is turned off.
waitForCompletion(vibrationThread, /* timeout= */ latency + TEST_TIMEOUT_MILLIS);
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.CANCELLED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
assertFalse(vibrationThread.getVibrators().get(VIBRATOR_ID).isVibrating());
}
@@ -968,7 +967,7 @@
waitForCompletion(vibrationThread, /* timeout= */ 50);
waitForCompletion(cancellingThread);
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.CANCELLED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
assertFalse(vibrationThread.getVibrators().get(1).isVibrating());
assertFalse(vibrationThread.getVibrators().get(2).isVibrating());
}
@@ -1000,7 +999,7 @@
waitForCompletion(vibrationThread, /* timeout= */ 50);
waitForCompletion(cancellingThread);
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.CANCELLED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
assertFalse(vibrationThread.getVibrators().get(1).isVibrating());
assertFalse(vibrationThread.getVibrators().get(2).isVibrating());
}
@@ -1020,11 +1019,179 @@
verify(mVibrationToken).linkToDeath(same(thread), eq(0));
verify(mVibrationToken).unlinkToDeath(same(thread), eq(0));
- verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.CANCELLED));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
assertFalse(mVibratorProviders.get(VIBRATOR_ID).getEffectSegments().isEmpty());
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
}
+ @Test
+ public void vibrate_waveformWithRampDown_addsRampDownAfterVibrationCompleted() {
+ int rampDownDuration = 15;
+ mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
+ new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
+ mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
+ mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
+
+ long vibrationId = 1;
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ new long[]{5, 5, 5}, new int[]{60, 120, 240}, -1);
+ VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
+ waitForCompletion(thread);
+
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+
+ // Duration extended for 5 + 5 + 5 + 15.
+ assertEquals(Arrays.asList(expectedOneShot(30)),
+ mVibratorProviders.get(VIBRATOR_ID).getEffectSegments());
+ List<Float> amplitudes = mVibratorProviders.get(VIBRATOR_ID).getAmplitudes();
+ assertTrue(amplitudes.size() > 3);
+ assertEquals(expectedAmplitudes(60, 120, 240), amplitudes.subList(0, 3));
+ for (int i = 3; i < amplitudes.size(); i++) {
+ assertTrue(amplitudes.get(i) < amplitudes.get(i - 1));
+ }
+ }
+
+ @Test
+ public void vibrate_waveformWithRampDown_triggersCallbackWhenOriginalVibrationEnds() {
+ int rampDownDuration = 10_000;
+ mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
+ new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
+ mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
+ mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
+
+ long vibrationId = 1;
+ VibrationEffect effect = VibrationEffect.createOneShot(10, 200);
+ VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
+
+ // Vibration completed but vibrator not yet released.
+ verify(mThreadCallbacks, timeout(TEST_TIMEOUT_MILLIS)).onVibrationCompleted(eq(vibrationId),
+ eq(Vibration.Status.FINISHED));
+ verify(mThreadCallbacks, never()).onVibratorsReleased();
+
+ // Thread still running ramp down.
+ assertTrue(thread.isAlive());
+
+ // Duration extended for 10 + 10000.
+ assertEquals(Arrays.asList(expectedOneShot(10_010)),
+ mVibratorProviders.get(VIBRATOR_ID).getEffectSegments());
+
+ // Will stop the ramp down right away.
+ thread.cancelImmediately();
+ waitForCompletion(thread);
+
+ // Does not cancel already finished vibration, but releases vibrator.
+ verify(mThreadCallbacks, never()).onVibrationCompleted(eq(vibrationId),
+ eq(Vibration.Status.CANCELLED));
+ verify(mThreadCallbacks).onVibratorsReleased();
+ }
+
+ @Test
+ public void vibrate_waveformCancelledWithRampDown_addsRampDownAfterVibrationCancelled()
+ throws Exception {
+ int rampDownDuration = 15;
+ mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
+ new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
+ mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
+ mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
+
+ long vibrationId = 1;
+ VibrationEffect effect = VibrationEffect.createOneShot(10_000, 240);
+ VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
+ assertTrue(waitUntil(t -> t.getVibrators().get(VIBRATOR_ID).isVibrating(), thread,
+ TEST_TIMEOUT_MILLIS));
+ thread.cancel();
+ waitForCompletion(thread);
+
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.CANCELLED);
+
+ // Duration extended for 10000 + 15.
+ assertEquals(Arrays.asList(expectedOneShot(10_015)),
+ mVibratorProviders.get(VIBRATOR_ID).getEffectSegments());
+ List<Float> amplitudes = mVibratorProviders.get(VIBRATOR_ID).getAmplitudes();
+ assertTrue(amplitudes.size() > 1);
+ for (int i = 1; i < amplitudes.size(); i++) {
+ assertTrue(amplitudes.get(i) < amplitudes.get(i - 1));
+ }
+ }
+
+ @Test
+ public void vibrate_predefinedWithRampDown_doesNotAddRampDown() {
+ int rampDownDuration = 15;
+ mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
+ new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
+ mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
+ mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
+ mVibratorProviders.get(VIBRATOR_ID).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
+
+ long vibrationId = 1;
+ VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
+ VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
+ waitForCompletion(thread);
+
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+
+ assertEquals(Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_CLICK)),
+ mVibratorProviders.get(VIBRATOR_ID).getEffectSegments());
+ assertTrue(mVibratorProviders.get(VIBRATOR_ID).getAmplitudes().isEmpty());
+ }
+
+ @Test
+ public void vibrate_composedWithRampDown_doesNotAddRampDown() {
+ int rampDownDuration = 15;
+ mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
+ new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
+ mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
+ mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL,
+ IVibrator.CAP_COMPOSE_EFFECTS);
+ mVibratorProviders.get(VIBRATOR_ID).setSupportedPrimitives(
+ VibrationEffect.Composition.PRIMITIVE_CLICK);
+
+ long vibrationId = 1;
+ VibrationEffect effect = VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .compose();
+ VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
+ waitForCompletion(thread);
+
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+
+ assertEquals(
+ Arrays.asList(expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 0)),
+ mVibratorProviders.get(VIBRATOR_ID).getEffectSegments());
+ assertTrue(mVibratorProviders.get(VIBRATOR_ID).getAmplitudes().isEmpty());
+ }
+
+ @Test
+ public void vibrate_pwleWithRampDown_doesNotAddRampDown() {
+ int rampDownDuration = 15;
+ mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
+ new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
+ mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
+ FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
+ fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL,
+ IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
+ fakeVibrator.setMinFrequency(100);
+ fakeVibrator.setResonantFrequency(150);
+ fakeVibrator.setFrequencyResolution(50);
+ fakeVibrator.setMaxAmplitudes(1, 1, 1);
+ fakeVibrator.setPwleSizeMax(2);
+
+ long vibrationId = 1;
+ VibrationEffect effect = VibrationEffect.startWaveform().addRamp(1, 1).build();
+ VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
+ waitForCompletion(thread);
+
+ verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
+ verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
+
+ assertEquals(Arrays.asList(expectedRamp(0, 1, 150, 150, 1)),
+ fakeVibrator.getEffectSegments());
+ assertTrue(fakeVibrator.getAmplitudes().isEmpty());
+ }
+
private void mockVibrators(int... vibratorIds) {
for (int vibratorId : vibratorIds) {
mVibratorProviders.put(vibratorId,
@@ -1042,7 +1209,7 @@
}
private VibrationThread startThreadAndDispatcher(Vibration vib) {
- VibrationThread thread = new VibrationThread(vib, mEffectAdapter,
+ VibrationThread thread = new VibrationThread(vib, mVibrationSettings, mEffectAdapter,
createVibratorControllers(), mWakeLock, mIBatteryStatsMock, mThreadCallbacks);
doAnswer(answer -> {
thread.vibratorComplete(answer.getArgument(0));
@@ -1117,4 +1284,9 @@
.mapToObj(amplitude -> amplitude / 255f)
.collect(Collectors.toList());
}
+
+ private void verifyCallbacksTriggered(long vibrationId, Vibration.Status expectedStatus) {
+ verify(mThreadCallbacks).onVibrationCompleted(eq(vibrationId), eq(expectedStatus));
+ verify(mThreadCallbacks).onVibratorsReleased();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index 9117ae6..77003b2 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -67,6 +67,7 @@
import android.os.test.TestLooper;
import android.os.vibrator.PrebakedSegment;
import android.os.vibrator.PrimitiveSegment;
+import android.os.vibrator.VibrationEffectSegment;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.view.InputDevice;
@@ -470,13 +471,14 @@
mockVibrators(1);
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1);
mVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM);
- fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
+ fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK,
+ VibrationEffect.EFFECT_HEAVY_CLICK, VibrationEffect.EFFECT_DOUBLE_CLICK);
setRingerMode(AudioManager.RINGER_MODE_NORMAL);
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0);
VibratorManagerService service = createSystemReadyService();
- vibrate(service, VibrationEffect.createOneShot(1, 1), RINGTONE_ATTRS);
+ vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), RINGTONE_ATTRS);
// Wait before checking it never played.
assertFalse(waitUntil(s -> !fakeVibrator.getEffectSegments().isEmpty(),
service, /* timeout= */ 50));
@@ -484,43 +486,52 @@
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 1);
service = createSystemReadyService();
- vibrate(service, VibrationEffect.createOneShot(1, 10), RINGTONE_ATTRS);
+ vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK), RINGTONE_ATTRS);
assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 1,
service, TEST_TIMEOUT_MILLIS));
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0);
service = createSystemReadyService();
- vibrate(service, VibrationEffect.createOneShot(1, 100), RINGTONE_ATTRS);
+ vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK), RINGTONE_ATTRS);
assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 2,
service, TEST_TIMEOUT_MILLIS));
- assertEquals(Arrays.asList(10 / 255f, 100 / 255f),
- mVibratorProviders.get(1).getAmplitudes());
+ assertEquals(
+ Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_HEAVY_CLICK),
+ expectedPrebaked(VibrationEffect.EFFECT_DOUBLE_CLICK)),
+ mVibratorProviders.get(1).getEffectSegments());
}
@Test
public void vibrate_withPowerMode_usesPowerModeState() throws Exception {
mockVibrators(1);
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1);
- fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
+ fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_TICK, VibrationEffect.EFFECT_CLICK,
+ VibrationEffect.EFFECT_HEAVY_CLICK, VibrationEffect.EFFECT_DOUBLE_CLICK);
VibratorManagerService service = createSystemReadyService();
mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
- vibrate(service, VibrationEffect.createOneShot(1, 1), HAPTIC_FEEDBACK_ATTRS);
- vibrate(service, VibrationEffect.createOneShot(2, 2), RINGTONE_ATTRS);
+ vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_TICK), HAPTIC_FEEDBACK_ATTRS);
+ vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), RINGTONE_ATTRS);
assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 1,
service, TEST_TIMEOUT_MILLIS));
mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE);
- vibrate(service, VibrationEffect.createOneShot(3, 3), /* attributes= */ null);
+ vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK),
+ /* attrs= */ null);
assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 2,
service, TEST_TIMEOUT_MILLIS));
- vibrate(service, VibrationEffect.createOneShot(4, 4), NOTIFICATION_ATTRS);
+ vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK),
+ NOTIFICATION_ATTRS);
assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 3,
service, TEST_TIMEOUT_MILLIS));
- assertEquals(Arrays.asList(2 / 255f, 3 / 255f, 4 / 255f), fakeVibrator.getAmplitudes());
+ assertEquals(
+ Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_CLICK),
+ expectedPrebaked(VibrationEffect.EFFECT_HEAVY_CLICK),
+ expectedPrebaked(VibrationEffect.EFFECT_DOUBLE_CLICK)),
+ mVibratorProviders.get(1).getEffectSegments());
}
@Test
@@ -836,7 +847,6 @@
vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), RINGTONE_ATTRS);
assertEquals(4, fakeVibrator.getEffectSegments().size());
- assertEquals(1, fakeVibrator.getAmplitudes().size());
// Notification vibrations will be scaled with SCALE_VERY_HIGH.
assertTrue(0.6 < fakeVibrator.getAmplitudes().get(0));
@@ -957,6 +967,10 @@
assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
}
+ private VibrationEffectSegment expectedPrebaked(int effectId) {
+ return new PrebakedSegment(effectId, false, VibrationEffect.EFFECT_STRENGTH_MEDIUM);
+ }
+
private void mockCapabilities(long... capabilities) {
when(mNativeWrapperMock.getCapabilities()).thenReturn(
Arrays.stream(capabilities).reduce(0, (a, b) -> a | b));
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index 825e53e..f9663f2 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -279,6 +279,36 @@
}
@Test
+ public void testReadXml_noLongerMigrateFromSettings() throws Exception {
+ for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
+ ManagedServices service = new TestManagedServicesNoSettings(getContext(), mLock,
+ mUserProfiles, mIpm, approvalLevel);
+
+ // approved services aren't in xml
+ TypedXmlPullParser parser = Xml.newFastPullParser();
+ parser.setInput(new BufferedInputStream(new ByteArrayInputStream(new byte[]{})),
+ null);
+ writeExpectedValuesToSettings(approvalLevel);
+
+ service.migrateToXml();
+ // No crash? success
+
+ ArrayMap<Integer, String> verifyMap = approvalLevel == APPROVAL_BY_COMPONENT
+ ? mExpectedPrimary.get(service.mApprovalLevel)
+ : mExpectedSecondary.get(service.mApprovalLevel);
+ for (int userId : verifyMap.keySet()) {
+ for (String verifyValue : verifyMap.get(userId).split(":")) {
+ if (!TextUtils.isEmpty(verifyValue)) {
+ assertFalse("service type " + service.mApprovalLevel + ":"
+ + verifyValue + " is allowed for user " + userId,
+ service.isPackageOrComponentAllowed(verifyValue, userId));
+ }
+ }
+ }
+ }
+ }
+
+ @Test
public void testReadXml() throws Exception {
for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
@@ -1766,4 +1796,25 @@
return true;
}
}
+
+ class TestManagedServicesNoSettings extends TestManagedServices {
+
+ public TestManagedServicesNoSettings(Context context, Object mutex, UserProfiles userProfiles,
+ IPackageManager pm, int approvedServiceType) {
+ super(context, mutex, userProfiles, pm, approvedServiceType);
+ }
+
+ @Override
+ protected Config getConfig() {
+ Config c = super.getConfig();
+ c.secureSettingName = null;
+ c.secondarySettingName = null;
+ return c;
+ }
+
+ @Override
+ public boolean shouldReflectToSettings() {
+ return false;
+ }
+ }
}
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 b7713a9..a1f1610 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -46,6 +46,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_LEGACY_SPLASH_SCREEN;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
@@ -111,11 +112,13 @@
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
+import android.os.Build;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
+import android.provider.DeviceConfig;
import android.util.MergedConfiguration;
import android.util.MutableBoolean;
import android.view.DisplayInfo;
@@ -135,6 +138,7 @@
import com.android.internal.R;
import com.android.server.wm.Task.ActivityState;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -2457,6 +2461,40 @@
assertNoStartingWindow(activity);
}
+ private void testLegacySplashScreen(int targetSdk, int verifyType) {
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ activity.mTargetSdk = targetSdk;
+ activity.addStartingWindow(mPackageName,
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
+ false, false);
+ waitUntilHandlersIdle();
+ assertHasStartingWindow(activity);
+ assertEquals(activity.mStartingData.mTypeParams & TYPE_PARAMETER_LEGACY_SPLASH_SCREEN,
+ verifyType);
+ activity.removeStartingWindow();
+ waitUntilHandlersIdle();
+ assertNoStartingWindow(activity);
+ }
+
+ @Test
+ public void testCreateRemoveLegacySplashScreenWindow() {
+ registerTestStartingWindowOrganizer();
+ DeviceConfig.Properties properties = DeviceConfig.getProperties(
+ DeviceConfig.NAMESPACE_WINDOW_MANAGER);
+ try {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ "splash_screen_exception_list", DEFAULT_COMPONENT_PACKAGE_NAME, false);
+ testLegacySplashScreen(Build.VERSION_CODES.R, TYPE_PARAMETER_LEGACY_SPLASH_SCREEN);
+ testLegacySplashScreen(Build.VERSION_CODES.S, 0);
+ } finally {
+ try {
+ DeviceConfig.setProperties(properties);
+ } catch (DeviceConfig.BadConfigException e) {
+ Assert.fail(e.getMessage());
+ }
+ }
+ }
+
@Test
public void testTransferStartingWindow() {
registerTestStartingWindowOrganizer();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 4872ec5..f35e85c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -105,7 +105,8 @@
public void setUp() throws Exception {
mInitialConstrainDisplayApisFlags = DeviceConfig.getProperties(
NAMESPACE_CONSTRAIN_DISPLAY_APIS);
- clearConstrainDisplayApisFlags();
+ DeviceConfig.setProperties(
+ new Properties.Builder(NAMESPACE_CONSTRAIN_DISPLAY_APIS).build());
}
@After
@@ -595,7 +596,6 @@
verify(mTask).onSizeCompatActivityChanged();
ActivityManager.RunningTaskInfo taskInfo = mTask.getTaskInfo();
- assertEquals(mActivity.appToken, taskInfo.topActivityToken);
assertTrue(taskInfo.topActivityInSizeCompat);
// Make the activity resizable again by restarting it
@@ -611,7 +611,6 @@
verify(mTask).onSizeCompatActivityChanged();
taskInfo = mTask.getTaskInfo();
- assertEquals(mActivity.appToken, taskInfo.topActivityToken);
assertFalse(taskInfo.topActivityInSizeCompat);
}
@@ -630,7 +629,6 @@
verify(mTask).onSizeCompatActivityChanged();
ActivityManager.RunningTaskInfo taskInfo = mTask.getTaskInfo();
- assertEquals(mActivity.appToken, taskInfo.topActivityToken);
assertTrue(taskInfo.topActivityInSizeCompat);
// Create another Task to hold another size compat activity.
@@ -651,7 +649,6 @@
verify(mTask, never()).onSizeCompatActivityChanged();
taskInfo = secondTask.getTaskInfo();
- assertEquals(secondActivity.appToken, taskInfo.topActivityToken);
assertTrue(taskInfo.topActivityInSizeCompat);
}
@@ -923,7 +920,7 @@
@Test
@DisableCompatChanges({ActivityInfo.ALWAYS_SANDBOX_DISPLAY_APIS})
- public void testAlwaysSandboxDisplayApis_configDisabled_sandboxingNotApplied() {
+ public void testAlwaysSandboxDisplayApis_configDisabled_sandboxingApplied() {
setUpDisplaySizeWithApp(1000, 1200);
// Make the task root resizable.
@@ -935,7 +932,7 @@
activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);
- // Activity max bounds be sandboxed due to letterbox and the config being disabled.
+ // Activity max bounds should be sandboxed due to letterbox and the config being disabled.
assertActivityMaxBoundsSandboxed(activity);
}
@@ -965,6 +962,27 @@
}
@Test
+ public void testAlwaysConstrainDisplayApisDeviceConfig_packageInRange_sandboxingApplied() {
+ setUpDisplaySizeWithApp(1000, 1200);
+
+ setAlwaysConstrainDisplayApisFlag(
+ "com.android.frameworks.wmtests:20:,com.android.other::,"
+ + "com.android.frameworks.wmtests:0:10");
+
+ // Make the task root resizable.
+ mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;
+
+ // Create an activity with a max aspect ratio on the same task.
+ final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
+ RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+ activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);
+
+ // Resizable activity is sandboxed due to match with flag.
+ assertActivityMaxBoundsSandboxed(activity);
+ }
+
+ @Test
@EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
public void testOverrideMinAspectRatioMedium() {
@@ -2120,8 +2138,8 @@
value, /* makeDefault= */ false);
}
- private static void clearConstrainDisplayApisFlags() {
- setNeverConstrainDisplayApisFlag(null);
- setNeverConstrainDisplayApisAllPackagesFlag(null);
+ private static void setAlwaysConstrainDisplayApisFlag(@Nullable String value) {
+ DeviceConfig.setProperty(NAMESPACE_CONSTRAIN_DISPLAY_APIS, "always_constrain_display_apis",
+ value, /* makeDefault= */ false);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index a1b3159..d6a8401 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -1229,7 +1229,6 @@
verify(organizer).onTaskInfoChanged(infoCaptor.capture());
RunningTaskInfo info = infoCaptor.getValue();
assertEquals(rootTask.mTaskId, info.taskId);
- assertEquals(activity.appToken, info.topActivityToken);
assertTrue(info.topActivityInSizeCompat);
// Ensure task info show top activity that is not in foreground as not in size compat.
@@ -1240,7 +1239,6 @@
verify(organizer).onTaskInfoChanged(infoCaptor.capture());
info = infoCaptor.getValue();
assertEquals(rootTask.mTaskId, info.taskId);
- assertEquals(activity.appToken, info.topActivityToken);
assertFalse(info.topActivityInSizeCompat);
// Ensure task info show non size compat top activity as not in size compat.
@@ -1252,7 +1250,6 @@
verify(organizer).onTaskInfoChanged(infoCaptor.capture());
info = infoCaptor.getValue();
assertEquals(rootTask.mTaskId, info.taskId);
- assertEquals(activity.appToken, info.topActivityToken);
assertFalse(info.topActivityInSizeCompat);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index f848ce5..ed18d26 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -28,6 +28,8 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -360,6 +362,15 @@
}
@Test
+ public void testTopActivityUiModeChangeScheduleConfigChange() {
+ final ActivityRecord activity = createActivityRecord(mWpc);
+ activity.mVisibleRequested = true;
+ doReturn(true).when(activity).setOverrideNightMode(anyInt());
+ mWpc.updateNightModeForAllActivities(Configuration.UI_MODE_NIGHT_YES);
+ verify(activity).ensureActivityConfiguration(anyInt(), anyBoolean());
+ }
+
+ @Test
public void testTopActivityDisplayAreaMatchesTopMostActivity_noActivities() {
assertNull(mWpc.getTopActivityDisplayArea());
}